-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature]: Parent loader data availability in child loader #9188
Comments
We're stick with this as well |
This is not likely to be implemented. A similar thing is answered in the Remix FAQ: https://remix.run/docs/en/v1/pages/faq#how-can-i-have-a-parent-route-loader-validate-the-user-and-protect-all-child-routes Loaders are called in parallel, so they cannot block each other or provide each other data. In the specific case of needing an ID from a parent loader, you would get that via the URL params. E.g., (Bring on the thumbs downs... 😞) |
What is the best way to handle passing access tokens then? I have a top-level "loader" that performs authentication and retrieves an access token. But the "children" loaders can't access the access token. My workaround is to use "useEffect" hooks in my children components but that robs me of all the niceties that the data loaders provide. |
You could store that access token in a cookie and access it from your other loaders by reading request.headers |
https://jankraus.net/2022/04/16/access-remix-route-data-in-other-routes/ This was useful for me and I guess it will be useful to some people that get here |
@machour No, because the other loaders run before the access token has been retrieved by the parent loader. The fact that parents are not initialized before children is a much bigger issue than where to store info (cookies etc). The location only matters after one has dealt with ordering. Remix FAQ says "This is probably not different than what you were doing before Remix, it might just be more obvious now". No, wrong, it's much different. Previously, when our app didn't have URL-based routing,
I am baffled that this is considered unimportant in react-router... so unimportant that the documentation doesn't even mention this surprising behavior. (It's also strange that |
this is really a huge problem. I end up with only skeletal root component (just one div + outlet), and everything in leaf routes and components. Loaders are just in leaf routes. Only other alternative I can think up was give up on loaders and use useEffect() |
Could you use react query and just pass the query client into the route loader and then fetch the data from the query cache? |
I worked around it by putting the router inside another component that I render via React.lazy. We call a signIn method in the bootstrapping phase, prior to rendering the main React app tho, which is probably not what others are doing. We don't use a a loader to get config and token. More or less like this: const LazyApp = lazy(() => import('./AppContainer'));
|
@timdorr this is not true:
Well first of all they aren't called in parallel, they are started asynchronously which is entirely different but that's not my main gripe. Assuming that's what you meant, of course they can still block each other, that's exactly what |
What you all want is middleware. And before that, the upcoming Keep in mind that the RR APIs were back-ported from Remix and as we've identified Remix constraints that don't necessarily apply, we've taken steps to ease them for SPA's. In Remix, loaders are very much called in parallel - in separate HTTP requests running in different processes and potentially even on different servers, so it is impossible to provide access to other loader data. Another approach worth considering in RR because it's all running in the browser - you can share singletons across all of your loaders so I would just create a |
I'd love to see an example implementation of Like you described, I want to be able to get a logged-in user's info from every loader / action, not just the /login route. |
You cannot do the same singleton in Remix because:
Right now in Remix, I would either:
Or wait for middleware |
For anyone coming here, it's now part of Remix itself to do this: https://remix.run/docs/en/main/hooks/use-route-loader-data
|
This isn't what we are after, this only makes the data available in the child components, not the child loader. |
Hey, is there some news about this? Maybe I missing something but can't find correct pattern for this. |
@alexshelkov This was closed in 2022 as "not planned". For what it's worth, we "solved" the issue by not using loaders. Instead we typically use effects like useEffect(() => {
maybeLoadInitialStuff(model).then(() => {
// load more stuff
});
}, [ stuffId ]); where let loadInitialStuffPromise: Promise<void>;
export function maybeLoadInitialStuff(model: ViewModel) {
return loadInitialStuffPromise ??= maybeLoadInitialStuffCore(model);
}
async function maybeLoadInitialStuffCore(model: ViewModel) {
// Load stuff that everything on the page needs
} In strict mode, using effects means that your inner stuff will be loaded twice, but there are ways around this. |
Complete feature for dataStrategy has been updated in |
What is the new or updated feature that you are suggesting?
Currently, components are able to get data from parent loaders with
useRouteLoaderData
. Since this is a hook, it can not be called in a loader function and so there is no way to make child fetches dependent on parent fetches.Proposed API:
Why should this feature be included?
Many cases for dependent fetches.
The text was updated successfully, but these errors were encountered: