Skip to content

Commit

Permalink
checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Feb 20, 2023
1 parent b87a7a0 commit 3581aec
Show file tree
Hide file tree
Showing 35 changed files with 4,709 additions and 3,814 deletions.
10 changes: 5 additions & 5 deletions docs/api/react/createRouteConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ const router = new Route()
})
```

- `onLoad: LoaderFn<AnyLoaderData, {}, {}>`
- `loader: LoaderFn<AnyLoaderData, {}, {}>`

This is used when you want you load data in your route which can later be read using 'useLoaderInstance' or 'useMatch'
This is used when you want you load data in your route which can later be read using 'useLoader' or 'useMatch'

```tsx
const rootRouter = route({
onLoad: async () => {
loader: async () => {
const posts = await axios
.get<PostType[]>('https://jsonplaceholder.typicode.com/posts')
.then((r) => r.data.slice(0, 10))
Expand Down Expand Up @@ -110,14 +110,14 @@ search: {}}) => void | ((match: {params: {};
search: {};
}) => void) | undefined) | undefined `

This function is called when moving from an inactive state to an active one. Likewise, when moving from an active to an inactive state, the return function (if provided) is called.
This function is called when moving from an inactive state to an active one. Likewise, when moving from an active to an inactive state, the return function (if provided) is called.

- `onTransition: ((match: {
params: {};
search: {};
}) => void) | undefined `

This function is called when the route remains active from one transition to the next.
This function is called when the route remains active from one transition to the next.

- `parseParams: ((rawParams: Record<never, string>) => Record<never, string>) | undefined`

Expand Down
6 changes: 3 additions & 3 deletions docs/api/react/useLoaderData.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
id: useLoaderInstance
title: useLoaderInstance
id: useLoader
title: useLoader
---

```tsx
const data = useLoaderInstance({
const data = useLoader({
from,
strict,
select,
Expand Down
26 changes: 3 additions & 23 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@
"to": "api/react/useLinkProps"
},
{
"label": "useLoaderInstance",
"to": "api/react/useLoaderInstance"
"label": "useLoader",
"to": "api/react/useLoader"
},
{
"label": "useMatch",
Expand Down Expand Up @@ -241,29 +241,9 @@
"to": "examples/react/basic?file=src%2Fmain.tsx"
},
{
"label": "Basic SSR",
"to": "examples/react/basic-ssr?file=src%2Froutes%2F__root.tsx"
},
{
"label": "Basic SSR w/ <html>",
"to": "examples/react/basic-ssr-with-html?file=src%2Froutes%2F__root.tsx"
},
{
"label": "Basic SSR Streaming (WIP)",
"to": "examples/react/basic-ssr-streaming?file=src%2Froutes%2F__root.tsx"
},
{
"label": "Kitchen Sink Single File",
"to": "examples/react/kitchen-sink-single-file?file=src%2Fmain.tsx"
},
{
"label": "Kitchen Sink Multi-File",
"label": "Kitchen Sink",
"to": "examples/react/kitchen-sink-multi-file?file=src%2Fmain.tsx"
},
{
"label": "Kitchen Sink SSR",
"to": "examples/react/kitchen-sink-ssr?file=src%2Froutes%2F__root.tsx"
},
{
"label": "Astro SSR",
"to": "examples/react/with-astro-ssr?file=src%2Froutes%2F__root.tsx"
Expand Down
6 changes: 3 additions & 3 deletions docs/guide/code-splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const route = new Route({

### Using the TanStack Router framework adapters `lazy` wrapper

Regardless of framework, if a route component has a static `preload` method attached to it, the Router will preload it when the route is matched with the `onLoad` option.
Regardless of framework, if a route component has a static `preload` method attached to it, the Router will preload it when the route is matched with the `loader` option.

If we were to **set this up manually** (so... don't do this) in React, it would look something like this:

Expand Down Expand Up @@ -50,13 +50,13 @@ The `lazy` wrapper not only implements `React.lazy()`, but automatically sets up

## Data Loader Splitting

Regardless of which data loading library you decide to go with, you may end up with a lot of data loaders that could potentially contribute to a large bundle size. If this is the case, you can code split your data loading logic using the Route's `onLoad` option:
Regardless of which data loading library you decide to go with, you may end up with a lot of data loaders that could potentially contribute to a large bundle size. If this is the case, you can code split your data loading logic using the Route's `loader` option:

```tsx
const route = new Route({
path: '/my-route',
component: MyComponent,
onLoad: async () => {
loader: async () => {
const data = await import('./data')
return { data }
},
Expand Down
64 changes: 32 additions & 32 deletions docs/guide/data-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ Just because TanStack Router works with any data-fetching library doesn't mean w

For the following examples, we'll show you the basics of data loading using **TanStack Loaders**, but as we've already mentioned, these same principles can be applied to any state management library worth it's salt. Let's get started!

## The `onLoad` route option
## The `loader` route option

The `onLoad` route option is a function that is called **every time** a route is matched and loaded for:
The `loader` route option is a function that is called **every time** a route is matched and loaded for:

- Navigating to a new route
- Refreshing the current route
- Preloading

Let's repeat that again. **Every time** someone navigates to a new route, refreshes the current route, or preloads a route, the matching routes' `onload` functions will be called.

> ⚠️ If you've used Remix or Next.js, you may be used to the idea that data loading only happens for routes on the page that _change_ when navigating. eg. If you were to navigate from `/posts` to `/posts/1`, the `loader`/`getServerSideProps `function for `/posts` would not be called again. This is not the case with TanStack Router. Every route's `onLoad` function will be called every time a route is loaded.
> ⚠️ If you've used Remix or Next.js, you may be used to the idea that data loading only happens for routes on the page that _change_ when navigating. eg. If you were to navigate from `/posts` to `/posts/1`, the `loader`/`getServerSideProps `function for `/posts` would not be called again. This is not the case with TanStack Router. Every route's `loader` function will be called every time a route is loaded.
The biggest reason for calling `onLoad` every time is to notify your data loading library that data is or will be required. How your data loading library uses that information may vary, but obviously, this pattern is hopeful that your data fetching library can cache and refetch in the background. If you're using TanStack Loaders or TanStack Query, this is the default behavior.
The biggest reason for calling `loader` every time is to notify your data loading library that data is or will be required. How your data loading library uses that information may vary, but obviously, this pattern is hopeful that your data fetching library can cache and refetch in the background. If you're using TanStack Loaders or TanStack Query, this is the default behavior.

Here is a simple example of using `onLoad` to fetch data for a route:
Here is a simple example of using `loader` to fetch data for a route:

```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postsLoader = new Loader({
key: 'posts',
Expand All @@ -75,40 +75,40 @@ const postsLoader = new Loader({
const postsRoute = new Route({
getParentPath: () => rootRoute,
path: 'posts',
async onLoad() {
async loader() {
// Wait for the loader to finish
await postsLoader.load()
},
component: () => {
// Access the loader's data, in this case with the useLoaderInstance hook
const posts = useLoaderInstance({ loader: postsLoader })
// Access the loader's data, in this case with the useLoader hook
const posts = useLoader({ loader: postsLoader })

return <div>...</div>
},
})
```

## `onLoad` Parameters
## `loader` Parameters

The `onLoad` function receives a single parameter, which is an object with the following properties:
The `loader` function receives a single parameter, which is an object with the following properties:

- `params` - The route's parsed path params
- `search` - The route's search query, parsed, validated and typed **including** inherited search params from parent routes
- `routeSearch` - The route's search query, parsed, validated and typed **excluding** inherited search params from parent routes
- `hash` - The route's hash
- `context` - The route's context object **including** inherited context from parent routes
- `routeContext` - The route's context object, **excluding** inherited context from parent routes
- `signal` - The route's abort signal which is cancelled when the route is unloaded or when the `onLoad` call becomes outdated.
- `signal` - The route's abort signal which is cancelled when the route is unloaded or when the `loader` call becomes outdated.

Using these parameters, we can do a lot of cool things. Let's take a look at a few examples

## Using Path Params

The `params` property of the `onLoad` function is an object containing the route's path params.
The `params` property of the `loader` function is an object containing the route's path params.

```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postLoader = new Loader({
key: 'post',
Expand All @@ -123,12 +123,12 @@ const postLoader = new Loader({
const postRoute = new Route({
getParentPath: () => postsRoute,
path: '$postId',
async onLoad({ params }) {
async loader({ params }) {
await postLoader.load({ variables: params.postId })
},
component: () => {
const { postId } = useParams({ from: postRoute.id })
const posts = useLoaderInstance({ loader: postLoader, variables: postId })
const posts = useLoader({ loader: postLoader, variables: postId })

return <div>...</div>
},
Expand All @@ -137,11 +137,11 @@ const postRoute = new Route({

## Using Search Params

The `search` and `routeSearch` properties of the `onLoad` function are objects containing the route's search params. `search` contains _all_ of the search params including parent search params. `routeSearch` only includes specific search params from this route. In this example, we'll use zod to validate and parse the search params for `/posts/$postId` route and use them in an `onload` function and our component.
The `search` and `routeSearch` properties of the `loader` function are objects containing the route's search params. `search` contains _all_ of the search params including parent search params. `routeSearch` only includes specific search params from this route. In this example, we'll use zod to validate and parse the search params for `/posts/$postId` route and use them in an `onload` function and our component.

```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postsLoader = new Loader({
key: 'posts',
Expand All @@ -159,12 +159,12 @@ const postsRoute = new Route({
validateSearch: z.object({
pageIndex: z.number().int().nonnegative().catch(0),
}),
async onLoad({ search }) {
async loader({ search }) {
await postsLoader.load({ variables: search.pageIndex })
},
component: () => {
const search = useSearchParams({ from: postsRoute.id })
const posts = useLoaderInstance({
const posts = useLoader({
loader: postsLoader,
variables: search.pageIndex,
})
Expand All @@ -176,13 +176,13 @@ const postsRoute = new Route({

## Using Context

The `context` and `routeContext` properties of the `onLoad` function are objects containing the route's context. `context` is the context object for the route including context from parent routes. `routeContext` is the context object for the route excluding context from parent routes. In this example, we'll create a `loaderClient` and inject it into our router's context. We'll then use that client in our `onLoad` function and our component.
The `context` and `routeContext` properties of the `loader` function are objects containing the route's context. `context` is the context object for the route including context from parent routes. `routeContext` is the context object for the route excluding context from parent routes. In this example, we'll create a `loaderClient` and inject it into our router's context. We'll then use that client in our `loader` function and our component.

> 🧠 Context is a powerful tool for dependency injection. You can use it to inject services, loaders, and other objects into your router and routes. You can also additively pass data down the route tree at every route using a route's `getContext` option.
```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postsLoader = new Loader({
key: 'posts',
Expand Down Expand Up @@ -211,11 +211,11 @@ const rootRoute = RootRoute.withRouterContext<{
const postsRoute = new Route({
getParentPath: () => rootRoute,
path: 'posts',
async onLoad({ context }) {
async loader({ context }) {
await context.loaderClient.getLoader({ key: 'posts' }).load()
},
component: () => {
const posts = useLoaderInstance({ key: 'posts' })
const posts = useLoader({ key: 'posts' })

return <div>...</div>
},
Expand All @@ -234,11 +234,11 @@ const router = new Router({

## Using the Abort Signal

The `signal` property of the `onLoad` function is an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) which is cancelled when the route is unloaded or when the `onLoad` call becomes outdated. This is useful for cancelling network requests when the route is unloaded or when the route's params change. Here is an example using TanStack Loader's signal passthrough:
The `signal` property of the `loader` function is an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) which is cancelled when the route is unloaded or when the `loader` call becomes outdated. This is useful for cancelling network requests when the route is unloaded or when the route's params change. Here is an example using TanStack Loader's signal passthrough:

```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postsLoader = new Loader({
key: 'posts',
Expand All @@ -253,12 +253,12 @@ const postsLoader = new Loader({
const postsRoute = new Route({
getParentPath: () => rootRoute,
path: 'posts',
async onLoad({ signal }) {
async loader({ signal }) {
// Pass the route's signal to the loader
await postsLoader.load({ signal })
},
component: () => {
const posts = useLoaderInstance({ loader: postsLoader })
const posts = useLoader({ loader: postsLoader })

return <div>...</div>
},
Expand All @@ -267,11 +267,11 @@ const postsRoute = new Route({

## Using the `prefetch` flag

The `prefetch` property of the `onLoad` function is a boolean which is `true` when the route is being loaded via a prefetch action. Some data loading libraries may handle prefetching differently than a standard fetch, so you may want to pass `prefetch` to your data loading library, or use it to execute the appropriate data loading logic. Here is an example using TanStack Loader and it's built-in `prefetch` flag:
The `prefetch` property of the `loader` function is a boolean which is `true` when the route is being loaded via a prefetch action. Some data loading libraries may handle prefetching differently than a standard fetch, so you may want to pass `prefetch` to your data loading library, or use it to execute the appropriate data loading logic. Here is an example using TanStack Loader and it's built-in `prefetch` flag:

```tsx
import { Route } from '@tanstack/router'
import { Loader, useLoaderInstance } from '@tanstack/react-loaders'
import { Loader, useLoader } from '@tanstack/react-loaders'

const postsLoader = new Loader({
key: 'posts',
Expand All @@ -285,12 +285,12 @@ const postsLoader = new Loader({
const postsRoute = new Route({
getParentPath: () => rootRoute,
path: 'posts',
async onLoad({ prefetch }) {
async loader({ prefetch }) {
// Pass the route's prefetch to the loader
await postsLoader.load({ prefetch })
},
component: () => {
const posts = useLoaderInstance({ loader: postsLoader })
const posts = useLoader({ loader: postsLoader })

return <div>...</div>
},
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/data-mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ import { useAction } from '@tanstack/react-actions'

function PostEditor() {
const params = useParams({ from: postEditRoute.id })
const postLoader = useLoaderInstance({
const postLoader = useLoader({
key: 'post',
variables: params.postId,
})
Expand Down Expand Up @@ -158,7 +158,7 @@ import { useAction } from '@tanstack/react-actions'

function PostEditor() {
const params = useParams({ from: postEditRoute.id })
const postLoader = useLoaderInstance({
const postLoader = useLoader({
key: 'post',
variables: params.postId,
})
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/preloading.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ You can also set the `preloadDelay` prop on individual `<Link>` components to ov

## Preloading with Data Loaders

Preloading is most useful when combined with your favorite data loading library. To make this easier, the `onLoad` route option function receives a `preload` boolean denoting whether the route is being preloaded or not. This allows you to load data differently depending on whether the user is navigating to the route or preloading it.
Preloading is most useful when combined with your favorite data loading library. To make this easier, the `loader` route option function receives a `preload` boolean denoting whether the route is being preloaded or not. This allows you to load data differently depending on whether the user is navigating to the route or preloading it.

Here's an example using TanStack Loaders:

Expand All @@ -47,7 +47,7 @@ const postsRoute = new Route({
getParentRoute: () => rootRoute,
path: 'posts',
component: PostsComponent,
onLoad: async ({ preload }) => {
loader: async ({ preload }) => {
postsLoader.load({ preload })
},
})
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/route-paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ A 404 / non-matching route is really just a fancy name for a [Splat / Catch-All]
Pathless layout routes are routes that do not have a `path` and instead an `id` to uniquely identify them. Pathless layout routes do not use path segments from the URL pathname, nor do they add path segments to it during linking. They can be used to:

- Wrap child routes with a layout component
- Enforce an `onLoad` requirement before displaying any child routes
- Enforce an `loader` requirement before displaying any child routes
- Validate and provide search params to child routes
- Provide fallbacks for error components or pending elements to child routes
- Provide shared context to all child routes
Expand Down
Loading

0 comments on commit 3581aec

Please sign in to comment.