Replies: 26 comments 4 replies
-
also, one more thing. [
{
path: "/",
element: Foo,
preload: fooResource,
routes: [
{
path: "/"
element: Bar,
preload: barResource
},
{
path: "/baz"
element: Baz,
preload: bazResource
},
{
path: "/qux"
element: qux,
preload: quxResource
}
]
},
{
path: "/other",
element: Other,
preload: otheResource,
}
] if we move from but if we move from |
Beta Was this translation helpful? Give feedback.
-
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Beta Was this translation helpful? Give feedback.
-
Thank you! Just implementing a Relay solution and I agree with the above. I would be great to have access to the return value of preload. |
Beta Was this translation helpful? Give feedback.
-
Stumbled upon this while I'm researching how to implement a deferred page transition and loading indicator, eg. waiting for the lazy component (or some other data), before actually executing the page switch. As I understand it's currently not possible at all in the v6 beta version without preload and useLocationPending, right? |
Beta Was this translation helpful? Give feedback.
-
@maggo If you use react experimental you can use Suspense and useTransition. This works with react router 6 but does not preload (e.g. load on mouseover or so). You can show a loading indicator before navigation though. |
Beta Was this translation helpful? Give feedback.
-
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Beta Was this translation helpful? Give feedback.
-
I didn't have chance to use the new react-router with preload yet, but if I had, I would probably do it like this: import { queryCache, useQuery } from "react-query"
function fetchTodos() {
return fetch("/todos").then(res => res.json())
}
function App() {
return (
<Routes>
<Route
path="todos"
preload={() => queryCache.prefetchQuery("todos", fetchTodos)}
element={<Todos />}
/>
</Routes>
)
}
function Todos() {
const todos = useQuery("todos", fetchTodos).data
return …
} |
Beta Was this translation helpful? Give feedback.
-
@phaux Yeah, I like this. But it should also pass the route params as argument of the callback function. |
Beta Was this translation helpful? Give feedback.
-
@phaux I've been trying to do something really similar with Relay experimental, but I'm getting an error ( See this examples: https://github.com/Hellzed/hello-relay-react-router-experimental |
Beta Was this translation helpful? Give feedback.
-
Not possible since cannot be called during render or by render itself... I think this is issue from react-router related to relay...
|
Beta Was this translation helpful? Give feedback.
-
@damikun Now I see!
Wouldn't it make sense for React Router v6 to always wrap the function passed to preload in (Haven't tried it, but do you think there would be any adverse effect in wrapping this whole block in |
Beta Was this translation helpful? Give feedback.
-
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
Beta Was this translation helpful? Give feedback.
-
Maybe it would be better to always call it inside the render function so we could hooks in it like queryLoader from Relay, but now it gives an error that the amount of hooks are not equal |
Beta Was this translation helpful? Give feedback.
-
Maybe something like a RouteContextProviderWithPreload instead of RouteContext.Provider function RouteContextProviderWithPreload({route, parentParams , params, index, location }) {
const preloaded = route?.preload(params, location, index)
return <RouteContext.Provider
children={route.element}
value={{
outlet,
params: readOnly<Params>({ ...parentParams, ...params }),
pathname: joinPaths([basename, pathname]),
route,
preloaded
}}
/>
} We then could use hooks like we want inside of the preload function <Route
path="todos"
preload={(params) => {
const [queryReference, loadQuery, disposeQuery] = useQueryLoader(query);
React.useEffect(() => {
loadQuery(LoadProjectQuery, { id: params.id });
}, [params]);
return queryReference;
}}
element={<Todos />}
/> I would also like if the returned result would be provided to the child route |
Beta Was this translation helpful? Give feedback.
-
It would also be nice if <LinkWithPreload existed where the preload function would be called onMouseIn or onMouseOver (prop setting?) inside the <LinkWithPreload we would have problems with the approach described above. So I think @damikun approach would be better where the preload function is wrapped inside a useEffect |
Beta Was this translation helpful? Give feedback.
-
Has somebody successfully integrated Relay with react-router using preloaded queries? I have a import React from 'react';
import { useQueryLoader } from 'react-relay/hooks';
import { Route } from 'react-router-dom';
import { Project, projectQuery } from '../pages/project';
import { ProjectQuery } from '../pages/project/__generated__/ProjectQuery.graphql';
import { RouteProps } from 'react-router';
type ProjectRouteProps = RouteProps;
function ProjectRoute(props: ProjectRouteProps) {
const [query, loadQuery] = useQueryLoader<ProjectQuery>(projectQuery);
console.log('render ProjectRoute - query is: ', query); // outputs: null
return (
<Route
path="/projects/:id"
element={query && <Project preloadedQuery={query} />}
preload={({ id }) => loadQuery({ id })}
{...props}
/>
);
}
export { ProjectRoute }; function App() {
// ...
return (
<Routes>
{/*...*/}
<ProjectRoute path="/projects/:id" />
{/*...*/}
</Routes>
);
} |
Beta Was this translation helpful? Give feedback.
-
I'm also in favor of this proposal, this would integrate nicely with the query preloading of relay! |
Beta Was this translation helpful? Give feedback.
-
Is there no way to currently preload in v6 beta? |
Beta Was this translation helpful? Give feedback.
-
You can preload but not with Relay since there is incompatibility between their implementations and relay functions.. You cannot call it from router preload... So if you don't need to call Relay or hook inside.. the preload will be fired... |
Beta Was this translation helpful? Give feedback.
-
Thanks everyone for weighing in on this issue. Our process for developing the preloading API in v6 will take into consideration how easy it is to ensure type safety between your data loaders and your component props. We definitely hear you there. We have some plans to add data loading capabilities to React Router post v6, but probably not in the initial v6 stable release. It will probably land in 6.1 or 6.2. Right now we are just trying to limit the scope of v6 so we can get it shipped quickly. |
Beta Was this translation helpful? Give feedback.
-
@mjackson At least we will get it. We can wait. Btw, thx for maintaining V3. |
Beta Was this translation helpful? Give feedback.
-
any update? |
Beta Was this translation helpful? Give feedback.
-
It's coming ! |
Beta Was this translation helpful? Give feedback.
-
See: #8855 |
Beta Was this translation helpful? Give feedback.
-
Any update? |
Beta Was this translation helpful? Give feedback.
-
locked since this is for an API that has shipped as |
Beta Was this translation helpful? Give feedback.
-
TL;DR
The current v6
preload
proposal appears difficult to statically type. Here is a proposal for an API that would be easier to type correctly. I implemented a small proof-of-concept using Flow (we don't use TypeScript) and everything looks good.Current API proposal
I know the v6
preload
API is still very early, but I'd like to contribute some thoughts to the discussion. If I'm understanding correctly, the proposal for the current preload API looks something like this:We use static typing extensively in our application and I'm struggling to envision a way to type the return value of
useResource
without resorting to an ugly type cast that is not statically verifiable.Statically-typeable API proposal
Here is an example API that would be much easier to statically type:
The
element
prop accepts either a React element or a function that accepts the resource (returned frompreload
) and returns a React element.To avoid prop-drilling, we could also pass the resource through context:
Full example
Here is a full example inspired by some of our application code, including our take on the "render-as-you-fetch" pattern. The application code is from a chat UI.
I would be happy to share my proof-of-concept Flow typings if they would help.
Other Considerations
preload
function would need to be written so that it is callable multiple times. At minimum, it would need to be called during the route's render so that its return value can be passed just-in-time to theelement
function (if it is a function and not a simple element). The application code inside thepreload
callback would take responsibility for caching network calls, etc.preload
could be triggered by a customizable list of events, such as 'mousedown' on an associated<Link>
. In that case, I could conceive of thepreload
function being called at least twice: once inside the mousedown handler and again when the route actually renders.preload
callback is NOT the place for that effect. A better place would be anonEnter
callback like RRv3.Beta Was this translation helpful? Give feedback.
All reactions