-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
docs: add HydrateFallback to the data-loading doc #12601
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,8 @@ Data is provided to the route component from `loader` and `clientLoader`. | |
|
||
Loader data is automatically serialized from loaders and deserialized in components. In addition to primitive values like strings and numbers, loaders can return promises, maps, sets, dates and more. | ||
|
||
The type for the `loaderData` prop is [automatically generated][type-safety]. | ||
|
||
## Client Data Loading | ||
|
||
`clientLoader` is used to fetch data on the client. This is useful for pages or full projects that you'd prefer to fetch data from the browser only. | ||
|
@@ -124,10 +126,58 @@ export async function loader({ params }: Route.LoaderArgs) { | |
} | ||
|
||
export async function clientLoader({ | ||
serverLoader, | ||
params, | ||
}: Route.ClientLoader) { | ||
const serverData = await serverLoader(); | ||
const res = await fetch(`/api/products/${params.pid}`); | ||
Comment on lines
+132
to
+133
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels redundant? In remix we showed off the common use cases in a dedicated page so maybe we pick what we think is the most common (presumably "skip the hop") and inline it into this doc but then we copy over the Remix doc and link off to it for advanced use cases? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah agreed. Initially I was combining that doc with the full stack data doc we had, but then realize we already had this doc I think a dedicated advanced data loading explanation or how-to is a good idea. I’ll try to put something together, even if it’s just a starting point we can improve upon later |
||
return { ...serverData, ...res.json() }; | ||
} | ||
|
||
export default function Product({ | ||
loaderData, | ||
}: Route.ComponentProps) { | ||
const { name, description } = loaderData; | ||
|
||
return ( | ||
<div> | ||
<h1>{name}</h1> | ||
<p>{description}</p> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
You can also force the client loader to run during hydration and before the page renders by setting the `hydrate` property on the function. In this situation you will want to render a `HydrateFallback` component to show a fallback UI while the client loader runs. | ||
|
||
```tsx filename=app/product.tsx | ||
// route("products/:pid", "./product.tsx"); | ||
import type { Route } from "./+types/product"; | ||
import { fakeDb } from "../db"; | ||
|
||
export async function loader({ params }: Route.LoaderArgs) { | ||
return fakeDb.getProduct(params.pid); | ||
} | ||
|
||
export async function clientLoader({ | ||
serverLoader, | ||
params, | ||
}: Route.ClientLoader) { | ||
const serverData = await serverLoader(); | ||
const res = await fetch(`/api/products/${params.pid}`); | ||
return res.json(); | ||
return { ...serverData, ...res.json() }; | ||
} | ||
|
||
// Note: if there is no `loader`, this is implied | ||
clientLoader.hydrate = true as const; | ||
|
||
export function HydrateFallback() { | ||
return ( | ||
<div> | ||
<h1>Product Loading...</h1> | ||
<p>Description loading...</p> | ||
</div> | ||
); | ||
} | ||
|
||
export default function Product({ | ||
|
@@ -154,3 +204,4 @@ See also: | |
|
||
[advanced_data_fetching]: ../tutorials/advanced-data-fetching | ||
[data]: ../../api/react-router/data | ||
[type-safety]: ../../explanation/type-safety |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might introduce
HydrateFallback
here since it can/should be used for this scenario where you have only aclientLoader
, and noloader
. In that scenario,clientLoader.hydrate
defaults to true because we have to run it on hydration if we have noloaderData
from the server.Then below you can mention:
loader
in addition to aclientLoader
, we can render the during SSR using the server loader dataclientLoader.hydrate=true
to run on hydration and provide aHydrateFallback
to render untilclientLoader
completes