Skip to content

Tanstack Start

Create stan-js store in your app:

store.ts
import { createScopedStore } from 'stan-js'
export const { StoreProvider, useScopedStore, useStore } = createScopedStore({
user: '',
counter: 0,
})

Calculate initial values (e.g. fetch some data using Server Functions or get it from search params) and pass that to StoreProvider:

__root.tsx
import {
createRootRoute,
HeadContent,
Outlet,
Scripts,
} from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
import { z } from 'zod'
import { fetchUser } from '../data'
import globals from '../globals.css?url'
import { StoreProvider } from '../store'
const RootComponent = () => {
const { user } = Route.useLoaderData()
const { counter } = Route.useSearch()
return (
<html>
<head>
<HeadContent />
</head>
<body>
<StoreProvider initialValue={{ user, counter }}>
<Outlet />
</StoreProvider>
<Scripts />
</body>
</html>
)
}
const getUser = createServerFn({ method: 'GET' }).handler(fetchUser)
export const Route = createRootRoute({
head: () => ({
meta: [
{
charSet: 'utf-8',
},
{
name: 'viewport',
content: 'width=device-width, initial-scale=1',
},
{
title: 'TanStack Start Starter',
},
],
links: [
{ rel: 'stylesheet', href: globals },
],
}),
component: RootComponent,
loader: async () => {
const user = await getUser()
return {
user,
}
},
validateSearch: z.object({
counter: z.number().optional(),
}),
})

Use useStore to access the store in your components:

index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { Counter } from '../components/Counter'
import { useStore } from '../store'
const Home = () => {
const { user } = useStore()
return (
<main>
<h1>
Hello {user}!
</h1>
<Counter />
</main>
)
}
export const Route = createFileRoute('/')({
component: Home,
})
Counter.tsx
import { useStore } from '../store'
export const Counter = () => {
const { counter, setCounter } = useStore()
return (
<section>
<button onClick={() => setCounter(prev => prev - 1)}>-</button>
<span>{counter}</span>
<button onClick={() => setCounter(prev => prev + 1)}>+</button>
</section>
)
}