-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Comments on the v6 preload API #7200
Comments
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 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
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. |
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? |
@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. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
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 …
} |
@phaux Yeah, I like this. But it should also pass the route params as argument of the callback function. |
@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 |
Not possible since cannot be called during render or by render itself... I think this is issue from react-router related to relay...
|
@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 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
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 |
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 |
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 |
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>
);
} |
I'm also in favor of this proposal, this would integrate nicely with the query preloading of relay! |
Is there no way to currently preload in v6 beta? |
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... |
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. |
@mjackson At least we will get it. We can wait. Btw, thx for maintaining V3. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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.The text was updated successfully, but these errors were encountered: