vike-react-zustand
v0.1.9
Published
<!-- WARNING: keep links absolute in this file so they work on NPM too -->
Readme
vike-react-zustand
Integrates Zustand state management into your vike-react app with SSR support.
[!NOTE] If you don't use any of your Zustand store during SSR, then you don't need
vike-react-zustand— you can use Zustand without any Vike integration.The
vike-react-zustandextension is about enabling you to use stores with SSR. See How it works.
Installation
Basic usagewithPageContext()useStoreVanilla()
Example
Populate store with +data
Version history
How it works
See also
Installation
npm install zustand vike-react-zustand- Extend
+config.js:// pages/+config.js import vikeReact from 'vike-react/config' import vikeReactZustand from 'vike-react-zustand/config' export default { // ... extends: [vikeReact, vikeReactZustand] }
[!NOTE] The
vike-react-zustandextension requiresvike-react.
Basic usage
Create a store using the create() function from vike-react-zustand:
// store.ts
import { create } from 'vike-react-zustand'
interface Store {
counter: number
increment: () => void
}
export const useStore = create<Store>()((set) => ({
counter: 0,
increment: () => set((state) => ({ counter: state.counter + 1 })),
}))[!NOTE] The API is the same as Zustand's
create().(Extra parentheses
()are required only when using TypeScript, as explained here.)
Use the store in your components:
import { useStore } from './store'
function Counter() {
const counter = useStore((state) => state.counter)
const increment = useStore((state) => state.increment)
return (
<button onClick={increment}>Counter {counter}</button>
)
}withPageContext()
The withPageContext middleware gives your store access to the Vike pageContext during initialization:
import { create, withPageContext } from 'vike-react-zustand'
interface Store {
user: any
nodeVersion: string
}
export const useStore = create<Store>()(
withPageContext((pageContext) => (set, get, store) => ({
// Access pageContext data
user: pageContext.user
}))
)API Reference
const nextStateCreatorFn = withPageContext((pageContext) => stateCreatorFn)pageContextstateCreatorFn: A state creator function that takessetfunction,getfunction andstoreas arguments. Usually, you will return an object with the methods you want to expose.- Returns: a state creator function.
useStoreVanilla()
Sometimes you need to access state in a non-reactive way or act upon the store. For these cases, you can use useStoreVanilla to directly access the vanilla store.
import { useStoreVanilla } from 'vike-react-zustand'
import { useStore } from './store'
function Component() {
const storeVanilla = useStoreVanilla(useStore)
// Subscribe to store changes
useEffect(
() => storeVanilla.subscribe(
state => console.log('Store changed:', state)
),
[]
)
// Get current state without subscribing to changes
const handleClick = () => {
const currentState = storeVanilla.getState()
storeVanilla.setState({ counter: currentState.counter + 5 })
}
return <button onClick={handleClick}>Add 5</button>
}[!NOTE] Middlewares that modify
setorgetare not applied togetStateandsetState.
Example
See examples/zustand/.
Populate store with +data
To populate your store with data fetched via the +data hook, use the withPageContext() middleware.
import { create, withPageContext } from 'vike-react-zustand'
import { immer } from 'zustand/middleware/immer'
import type { Data } from './+data'
type Todo = { text: string }
interface TodoStore {
todoItems: Todo[]
addTodo: (todo: Todo) => void
}
export const useTodoStore = create<TodoStore>()(
withPageContext((pageContext) =>
immer((set, get) => ({
todoItems: (pageContext.data as Data).todoItemsInitial,
addTodo(todo) {
set((state) => {
state.todoItems.push(todo)
})
},
})),
),
)See the To-Do List example at examples/zustand/.
Version history
See CHANGELOG.md.
How it works
The vike-react-zustand extension enables Zustand stores to work seamlessly with SSR:
- During SSR, store state is captured and serialized
- The serialized state is passed to the client
- On the client, the store is hydrated using the server-side state
The extension handles all the complexities of state transfer between server and client, ensuring your React components have access to the same state during both serer-side rendering and client-side hydration.
