I created a new app using this starter code from Tanstack Start/Router, and I'm unsure how to put in React Providers. There is no ReactDOM.render
call anywhere that the App component is rendered, and so it's not clear to me where they should go.
In client.tsx
there's something that looks analogous to the React renderer:
hydrateRoot(document, <StartClient router={router} />)
And I've tried wrapping <StartClient>
with my providers, but it doesn't like that. This is also the first time I've done anything with SSR, so I'm sure part of it is not really understanding how Tanstack is doing all that. And I haven't found anywhere in the Tanstack docs that show how to use providers like I need to. So far I have about 3 that I need for my app between context, libraries, and authentication. Where do I put them?
Put the provider in app/routes/__root.tsx
.
That component is rendered for every request on the server and when the client hydrates. it plays the same role that ReactDOM.render(<App …/>), _app.tsx do in Next.js or main.tsx in Vite.
// app/routes/__root.tsx
import {
Outlet,
createRootRoute,
HeadContent,
Scripts,
} from '@tanstack/react-router'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { AuthProvider } from '~/lib/auth'
import { ThemeProvider } from '~/lib/theme'
const queryClient = new QueryClient()
export const Route = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<RootDocument>
{/* providers go here */}
<QueryClientProvider client={queryClient}>
<AuthProvider>
<ThemeProvider>
{/* all your route components render inside <Outlet /> */}
<Outlet />
</ThemeProvider>
</AuthProvider>
</QueryClientProvider>
</RootDocument>
)
}
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html>
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
)
}
app/client.tsx should stay exactly as the starter mentioned, which is:
import { hydrateRoot } from 'react-dom/client'
import { StartClient } from '@tanstack/react-start'
import { createRouter } from './router'
hydrateRoot(document, <StartClient router={createRouter()} />)
<StartClient />
must be the root element that hydrates the markup sent by the server. Adding extra DOM around it, such as adding provider,s would break the checksum React uses in hydration and result in throwing error