remix: [Bug]: Loader data gets undefined when an error is thrown in a child route
Which Remix packages are impacted?
remix(Remix core)
What version of Remix are you using?
1.0.3
Steps to Reproduce
I couldn’t reproduce the bug with the remix template on Codesandbox, but this happens 100% of the time with the Remix Jokes tutorial. You can watch the bug in action at this moment in @kentcdodds’s lifestream yesterday. He asked if someone could open up an issue for it, so here I am.
I have created a public repo on Github with the code you are supposed to have when you have been following along the Jokes tutorial, just before beginning the “SEO with Meta tags” part. Here’s how to see the bug in action:
- Clone this repo
- Run
npm i - Create a .env file and add
DATABASE_URL="file:./dev.db"in it, along withSESSION_SECRET="whatever" - Seed the DB:
npx prisma db seed - Run the app:
npm run dev - Click “Read jokes”, then “Add your own” (or go to http://localhost:3000/jokes/new)
- Submit the form
- Kaboum!
Expected Behavior
An error thrown in a route action should be caught by the route’s error boundary (or the closest one above). The parent’s loader data shouldn’t become undefined when this happens.
Actual Behavior
The error occurring in the /jokes/new route action function isn’t handled by the route’s error boundary, instead, the /jokes route loader data becomes undefined, triggering an error that is caught by the root error boundary:
TypeError: Cannot read property 'user' of undefined
at `{data.user ? (` (./app/routes/jokes.tsx:50:16)
[...]
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 12
- Comments: 24 (11 by maintainers)
Commits related to this issue
- chore: re-work server runtime goals: - simplify shared server runtime - simplify loop that tracks boundaries - simplify how actions / loaders are called - make sure all boundary cases are surfaced pr... — committed to remix-run/remix by jacob-ebey 3 years ago
- wip: re-work server runtime (#864) chore: renamed componentDidCatchEmulator to appState chore: added a bunch of tests feat: strip error messages when not in development mode goals: - simplify s... — committed to remix-run/remix by jacob-ebey 3 years ago
- Test a failure in an action. Other action loaders are returning undefined. Kent Dodds has same issue. See video at: https://youtu.be/hsIWJpuxNj0?t=17466 https://youtu.be/hsIWJpuxNj0?t=17563 https://... — committed to ngbrown/remix-jokes-tutorial by ngbrown 2 years ago
- wip: re-work server runtime (#864) chore: renamed componentDidCatchEmulator to appState chore: added a bunch of tests feat: strip error messages when not in development mode goals: - simplify s... — committed to remix-run/react-router by jacob-ebey 3 years ago
I’ve added empty
CatchBoundarytoroutes/jokes.tsxlike this and it fixed it for me.Not sure why
Hi, Is there a fix for it (not a temporary fix)? If not, in the meanwhile, can you add the temporary fix to the docs?
Found another way of fixing it without creating empty
CatchBoundaryin/jokesyou can:<Scripts />toroot.tsx<Form>instead of HTML<form>for delete action.The way it works
<Form>will actually do request viafetchand prevent browser reload. I suspect if action throws an error in no-JS environment with full page reload Remix fails to properly loadentryContextfrom whichuseLoaderDatatakes its data.Updated to
v1.6.0in my jokes-tutorial-app now, and it seems to work much better now! 🎉Thank you so much for the fix, now I can continue with the tutorial 🥰👍
🤖 Hello there,
We just published version
v1.6.0which involves this issue. If you’d like to take it for a test run please try it out and let us know what you think!Thanks!
Why should empty boundaries be needed? I don’t think the official solution should be to add empty
ErrorBoundarys to every component with an<Outlet />. Maybe Remix can add that automatically though?This is still a bug with 1.5.0 with the no-JS server side render of an action (form submit) that throws in the Jokes app tutorial.
As a temporary fix I suggest to include placeholder
ErrorBoundaryandCatchBoundaryin parent routes if children can throw an error.Super confusing, and very frustrating.
Got to the “Add a delete capability …” part of the Jokes tutorial, and getting errors of not being able to read “user” from
undefinedwhen I try to click the delete button. The error happens injokes.tsx, which is the parent route of$jokeId.tsxand it makes no sense. What does the loader data of the parent route have to do with the child route? How can a child route cause a parent route loader data to suddenly beundefined? That’s very confusing, and makes no sense at all to me. Frankly, kind of killed my liking of Remix a bit for now, because I no longer feel I can trust/understand what’s going on. 😕Telling people to throw random catch/error boundaries around is not a solution.
Is this being actually fixed?
🤖 Hello there,
We just published version
v1.6.0-pre.0which involves this issue. If you’d like to take it for a test run please try it out and let us know what you think!Thanks!
Sorry for the frustration and negativity. Hope you can forgive me.
I was very excited to try out Remix, and got quite bummed out when I ran into this confusing bug while going through the main tutorial (the in-depth one) in the docs. I was prepared for things not being optimal, but was kind of expecting to at least be able to get through the tutorial without hitting a road-block there already. And when I found this bug-report that was reported several months ago, which seemed a bit forgotten(?), I just felt like sharing that frustration because it seems many beginners going through that tutorial run into the very same issue.
Hitting weird bugs like these when going through official beginner-tutorials feels kind of bad, because it’s very easy to enter “obviously, it’s unexperienced me who must have missed something, I must be dumb, because according to the tutorial that I just did, this should be working”-headspace. Could have shared my experience in a less negative and aggressive way though. Sorry again.
Fully aware that this is a very new framework that’s still under construction, and also fully aware that there’s probably a bunch of other things that are even more important for you guys to get fixed.
I’ve read about so many awesome features, and loved the presentations you guys had at the recent Remix and Reactathon-conferences. I just wanted to check it out for myself finally, instead of just reading blog posts and watching talks, and finally got the chance on a “look into whatever you want”-day at work today. 🙃
Excited to see how things develop further. Am subscribed to this bug, and will check out the tutorial and try to continue when this issue gets fixed. 🚀👍
@Svish I get that you’re frustrated but it sounds like software that has been open sourced for only 6 months is out of your risk tolerance. Workarounds are part of the story in the beginning–always has been, always will be, for every project.
We definitely should have fixed this by now, I agree, but we’re not cool with messages like yours. You have some more productive options than what you’ve done:
At this stage of my life and career in open source I have a pretty low tolerance level for comments like yours. Happy to have you here but consider this a warning. Please tone it down and be a productive member of the community.
Created a PR with explanation why it works this way.
The bug does not need database and secret to be reproduced. Here are slightly faster steps:
git@github.com:Xiphe/remix-error-action-loader-undefined.gitnpm install && npm run devCannot read properties of undefined (reading 'demos')which results from thisuseLoaderDatareturning undefined(moved from https://github.com/remix-run/remix/issues/582)