Skip to content

Commit

Permalink
TanStack Start Quickstart and Docs (#31133)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: c8701f5d2a25b97518645ea8635ab8bbec897949
  • Loading branch information
thomasballinger authored and Convex, Inc. committed Oct 29, 2024
1 parent 29e303d commit f9ca75a
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 8 deletions.
2 changes: 1 addition & 1 deletion docs/client/react/nextjs/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ with Convex, Next.js provides:

and more!

This pages covers the App Router variant of Next.js. Alternatively see the
This page covers the App Router variant of Next.js. Alternatively see the
[Pages Router](/docs/client/react/nextjs-pages-router/nextjs-pages-router.mdx)
version of this page.

Expand Down
112 changes: 112 additions & 0 deletions docs/client/react/tanstack-start.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
title: "TanStack Start"
sidebar_label: "TanStack Start"
sidebar_position: 150
---

[TanStack Start](https://tanstack.com/start/latest) is a new React web framework
with best-in-class typesafe routing.

When used with Convex, TanStack Start provides

- Live-updating queries with React Query (the React client for TanStack Query)
- Subscription session resumption, from SSR to live on the client
- Loader-based preloading and prefetching
- Consistent logical query timestamp during SSR
- Opt-in component-local SSR

and more!

This page describes the recommended way to use Convex with TanStack Start, via
React Query. The standard Convex React hooks work also with TanStack Start
without React Query, as do the
[React Query hooks](/docs/client/tanstack-query.mdx) without TanStack Start! But
using all three is a sweet spot.

<Admonition type="caution" title="TanStack Start is in Alpha">
TanStack Start is a new React framework currently in alpha. You can try it
today but there will probably be breaking changes made to it before a stable
release.
</Admonition>

## Getting started

Follow the [TanStack Start Quickstart](/docs/quickstart/tanstack-start.mdx) to
add Convex to a new TanStack Start project.

## Using Convex with React Query

You can read more about [React Query hooks](/docs/client/tanstack-query.mdx),
but a few highlights relevant to TanStack Start.

### Staying subscribed to queries

Convex queries in React Query continue to receive updates after the last
component subscribed to the query unmounts. The default for this behavior is 5
minutes and this value is configured with
[`gcTime`](https://tanstack.com/query/latest/docs/framework/react/guides/caching).

This is useful to know when debugging why a query result is already loaded: for
client side navigations, whether a subscription is already active can depend on
what pages were previously visited in a session.

### Using Convex React hooks

[Convex React](/docs/client/react.mdx) hooks like
[`usePaginatedQuery`](/api/modules/react#usepaginatedquery) can be used
alongside TanStack hooks. These hooks reference the same Convex Client so
there's still just one set of consistent query results in your app when these
are combined.

## Server-side Rendering

Using TanStack Start and Query with Convex makes it particularly easy to
live-update Convex queries on the client while also
[server-rendering](https://tanstack.com/query/v5/docs/framework/react/guides/ssr)
them.
[`useSuspenseQuery()`](https://tanstack.com/query/latest/docs/framework/react/reference/useSuspenseQuery)
is the simplest way to do this:

```ts
const { data } = useSuspenseQuery(convexQuery(api.messages.list, {}));
```

### Consistent client views

In the browser all Convex query subscriptions present a consistent,
at-the-same-logical-timestamp view of the database: if one query result reflects
a given mutation transaction, every other query result will too.

Server-side rendering is usually a special case: instead of a stateful WebSocket
session, on the server it's simpler to fetch query results ad-hoc. This can lead
to inconsistencies analogous to one REST endpoint returning results before a
mutation ran and another endpoint returning results after that change.

In TanStack Start, this issue is avoided by sending in a timestamp along with
each query: Convex uses the same timestamp for all queries.

### Loaders

To make client-side navigations faster you can add a
[loader](https://tanstack.com/router/latest/docs/framework/react/guide/external-data-loading#using-loaders-to-ensure-data-is-loaded)
to a route. By default, loaders will run when mousing over a link to that page.

```ts
export const Route = createFileRoute('/posts')({
loader: async (opts) => {
await opts.context.queryClient.ensureQueryData(
convexQuery(api.messages.list, {}),
);
};
component: () => {
const { data } = useSuspenseQuery(convexQuery(api.messages.list, {}));
return (
<div>
{data.map((message) => (
<Message key={message.id} post={message} />
))}
</div>
);
},
})
```
15 changes: 12 additions & 3 deletions docs/client/tanstack-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ sidebar_position: 325
import Setup from "!!raw-loader!@site/../demos/react-query/src/main.tsx";
import App from "!!raw-loader!@site/../demos/react-query/src/App.tsx";

If you already use [TanStack Query](https://tanstack.com/query/latest) the query
options function `convexQuery` may be useful in addition to the standard
[Convex React client](/client/react).
[TanStack Query](https://tanstack.com/query/latest) is an excellent, popular
library for managing requests to a server.

The
[`@convex-dev/react-query`](https://www.npmjs.com/package/@convex-dev/react-query)
library provides
[Query Option](https://tanstack.com/query/latest/docs/framework/react/guides/query-options)
functions for use with TanStack Query.

Not all features of the standard [Convex React client](/client/react) are
available through the TanStack Query APIs but you can use the two alongside each
other, dropping into the standard Convex React hooks as necessary.

<BetaAdmonition feature="The TanStack Query adapter" verb="is" />

Expand Down
4 changes: 3 additions & 1 deletion docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"typecheck",
"Typecheck",
"typechecked",
"typesafe",
"typeof",
"unauthed",
"unparameterized",
Expand All @@ -107,7 +108,8 @@
"webm",
"whsec",
"yourclientid",
"zoneinfo"
"zoneinfo",
"Linsley"
],
"ignoreRegExpList": ["/#[\\w-]+/", "/\\w+.png/"],
"enableFiletypes": ["mdx"]
Expand Down
7 changes: 4 additions & 3 deletions docs/quickstart/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import pageJs from "!!raw-loader!@site/../private-demos/quickstarts/nextjs-app-d
Convex is an all-in-one backend and database that integrates quickly and easily
with Next.js.

Once you've started below. See how to setup
[Server Rendering](/docs/client/react/nextjs/nextjs-server-rendering.mdx), and
[Hosting](/docs/production/hosting/hosting.mdx).
Once you've gotten started, see how to set up
[hosting](/docs/production/hosting/hosting.mdx)
[server rendering](/docs/client/react/nextjs/nextjs-server-rendering.mdx), and
[auth](https://docs.convex.dev/client/react/nextjs/).

</Admonition>

Expand Down
179 changes: 179 additions & 0 deletions docs/quickstart/tanstack-start.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
title: TanStack Start Quickstart
sidebar_label: TanStack Start
description: "Add Convex to a TanStack Start project"
hide_table_of_contents: true
sidebar_position: 200
---

import sampleData from "!!raw-loader!@site/../private-demos/quickstarts/tanstack-start/sampleData.jsonl";
import appRoutesRoot from "!!raw-loader!@site/../private-demos/quickstarts/tanstack-start/app/routes/__root.tsx";
import router from "!!raw-loader!@site/../private-demos/quickstarts/tanstack-start/app/router.tsx";
import index from "!!raw-loader!@site/../private-demos/quickstarts/tanstack-start/app/routes/index.tsx";
import tasks from "!!raw-loader!@site/../private-demos/quickstarts/tanstack-start/convex/tasks.ts";

<Admonition type="caution" title="TanStack Start is in Alpha">

[TanStack Start](https://tanstack.com/start/latest) is a new React framework
currently in alpha. You can try it today but there are likely to be breaking
changes before a stable release.

</Admonition>

To get setup quickly with Convex and TanStack Start run

<p>
<b>
<CodeWithCopyButton text="npm create convex@latest -- -t tanstack-start" />
</b>
</p>

or follow the guide below.

---

Learn how to query data from Convex in a TanStack Start site.

<StepByStep>
<Step title="Create a TanStack Start site">

The TanStack team intends to release a CLI template starter soon, but until the
official way to create a new TanStack Start site is to follow the TanStack Start
[getting started](https://tanstack.com/router/latest/docs/framework/react/start/getting-started)
guide.

Once you've finished you'll have a directory called myApp with a minimal
TanStack Start app in it.

```sh
.
├── app/
│ ├── routes/
│ │ ├── `index.tsx`
│ │ └── `__root.tsx`
│ ├── `client.tsx`
│ ├── `router.tsx`
│ ├── `routeTree.gen.ts`
│ └── `ssr.tsx`
├── `.gitignore`
├── `app.config.ts`
├── `package.json`
└── `tsconfig.json`
```

</Step>
<Step title="Install the Convex client and server library">
To get started with Convex install the `convex` package and a few React Query-related packages.

```sh
npm install convex @convex-dev/react-query @tanstack/react-router-with-query @tanstack/react-query
```

</Step>

<Step title="Update app/routes/__root.tsx">
Add a `QueryClient` to the router context to make React Query usable anywhere in the TanStack Start site.

<Snippet
source={appRoutesRoot}
title="app/routes/__root.tsx"
highlightPatterns={[ "createRootRouteWithContext", "QueryClient", "\\}\\>\\(\\)\\(\\{"]}
/>

</Step>

<Step title="Update app/router.tsx">
Replace the file `app/router.tsx` with these contents.

This creates a `ConvexClient` and a `ConvexQueryClient` and wires in a `ConvexProvider`.

<Snippet
source={router}
title="app/router.tsx"
/>

</Step>

<Step title="Set up a Convex dev deployment">
Next, run `npx convex dev`. This
will prompt you to log in with GitHub,
create a project, and save your production and deployment URLs.

It will also create a `convex/` folder for you
to write your backend API functions in. The `dev` command
will then continue running to sync your functions
with your dev deployment in the cloud.


```sh
npx convex dev
```

</Step>

<Step title="Create sample data for your database">
In a new terminal window, create a `sampleData.jsonl`
file with some sample data.

<Snippet
source={sampleData}
title="sampleData.jsonl"
/>

</Step>

<Step title="Add the sample data to your database">
Now that your project is ready, add a `tasks` table
with the sample data into your Convex database with
the `import` command.

```
npx convex import --table tasks sampleData.jsonl
```

</Step>

<Step title="Expose a database query">
Add a new file <JSDialectFileName name="tasks.ts" /> in the `convex/` folder
with a query function that loads the data.

Exporting a query function from this file
declares an API function named after the file
and the export name, `api.tasks.get`.

<Snippet
source={tasks}
title="convex/tasks.ts"
/>

</Step>

<Step title="Display the data in your app">
Replace the file `app/routes/index.tsx` with these contents.

The `useSuspenseQuery` hook renders the API function `api.tasks.get`
query result on the server initially, then it updates live in the browser.

<Snippet
source={index}
title="app/routes/index.tsx"
highlightPatterns={[ "useSuspenseQuery" ]}
/>

</Step>

<Step title="Start the app">
Start the app, open [http://localhost:3000](http://localhost:3000) in a browser,
and see the list of tasks.

```sh
npm run dev
```

</Step>

</StepByStep>

For more see the
[TanStack Start with Convex](/docs/client/react/tanstack-start.mdx) client
documentation page.
7 changes: 7 additions & 0 deletions src/QuickstartsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SvelteLogo from "@site/static/img/svelte-logo.svg";
import VueLogo from "@site/static/img/vue-logo.svg";
import AndroidLogo from "@site/static/img/android-logo.svg";
import SwiftLogo from "@site/static/img/swift-logo.svg";
import TanStackLogo from "@site/static/img/tanstack-logo.svg";
import React from "react";
import Link from "@docusaurus/Link";
import { ReactNode } from "@mdx-js/react/lib";
Expand Down Expand Up @@ -89,6 +90,12 @@ export function QuickstartsList() {
docId: "quickstart/remix",
label: "Remix",
},
{
icon: <TanStackLogo height={40} />,
href: "/quickstart/tanstack-start",
docId: "quickstart/tanstack-start",
label: "TanStack Start",
},
{
icon: <ExpoLogo height={40} />,
invertIcon: true,
Expand Down

0 comments on commit f9ca75a

Please sign in to comment.