Can't use persist with context implementation mentioned in the docs for Next.js #2350
-
*Edit: I reproduced the error on stackblitz here my code is the same as docs https://docs.pmnd.rs/zustand/guides/nextjs#app-router store fileimport { devtools, persist } from "zustand/middleware";
import { createStore } from "zustand/vanilla";
export type MainStoreState = {
selectedPropertyId: number | undefined;
selectedBusinessOwnerId: number | undefined;
selectedBusinessOwnerName: string | undefined;
};
export type MainStoreActions = {
updateSelectedPropertyId: (id: number) => void;
updateSelectedBusinessOwner: (id: number, name: string) => void;
};
export type MainStore = MainStoreState & MainStoreActions;
export const initMainStore = (): MainStoreState => {
return {
selectedPropertyId: undefined,
selectedBusinessOwnerId: undefined,
selectedBusinessOwnerName: undefined,
};
};
export const defaultInitState: MainStoreState = {
selectedPropertyId: undefined,
selectedBusinessOwnerId: undefined,
selectedBusinessOwnerName: undefined,
};
export const createMainStore = (
initState: MainStoreState = defaultInitState
) => {
return createStore<MainStore>()(
devtools(
persist(
set =>
({
...initState,
updateSelectedPropertyId: (id: number) => {
set(state => ({ ...state, selectedPropertyId: id }));
},
updateSelectedBusinessOwner: (id: number, name: string) => {
set(state => ({
...state,
selectedBusinessOwnerId: id,
selectedBusinessOwnerName: name,
}));
},
}) satisfies MainStore,
{
name: "main-store", // name of the item in the storage (must be unique)
skipHydration: true, // do not rehydrate this store after a full page load, we will rehydrate it manually
}
)
)
);
}; provider file"use client";
import { type ReactNode, createContext, useContext, useRef } from "react";
import { type StoreApi, useStore } from "zustand";
import {
type MainStore,
createMainStore,
initMainStore,
} from "@/stores/mainStore";
export const MainStoreContext = createContext<StoreApi<MainStore> | null>(null);
export interface MainStoreProviderProps {
children: ReactNode;
}
export const MainStoreProvider = ({ children }: MainStoreProviderProps) => {
const storeRef = useRef<StoreApi<MainStore>>();
if (!storeRef.current) {
storeRef.current = createMainStore(initMainStore());
}
return (
<MainStoreContext.Provider value={storeRef.current}>
{children}
</MainStoreContext.Provider>
);
};
export const useMainStore = <T,>(selector: (store: MainStore) => T): T => {
const mainStoreContext = useContext(MainStoreContext);
if (!mainStoreContext) {
throw new Error(`useMainStore must be use within MainStoreProvider`);
}
return useStore(mainStoreContext, selector);
}; the docs say that we can use this hook for nextjs// useStore.ts
import { useState, useEffect } from 'react'
const useStore = <T, F>(
store: (callback: (state: T) => unknown) => unknown,
callback: (state: T) => F,
) => {
const result = store(callback) as F
const [data, setData] = useState<F>()
useEffect(() => {
setData(result)
}, [result])
return data
}
export default useStore but that hook doesn't work with array destructuring syntax const [
selectedPropertyId,
updateSelectedPropertyId,
selectedBusinessOwnerId,
selectedBusinessOwnerName,
updateSelectedBusinessOwner,
] = useMainStore(state => [
state.selectedPropertyId,
state.updateSelectedPropertyId,
state.selectedBusinessOwnerId,
state.selectedBusinessOwnerName,
state.updateSelectedBusinessOwner,
]); so I went to try the other solution with skipHydration: trueand manually hydrate at the subscribed component inside useEffectuseEffect(() => {
useMainStore.persist.rehydrate();
}, []); but I get this error Property 'persist' does not exist on type '(selector: (store: MainStore) => T) => T'.ts(2339) |
Beta Was this translation helpful? Give feedback.
Answered by
dbritto-dev
Feb 21, 2024
Replies: 1 comment 12 replies
-
@1Mouse would you mind sharing us a minimal repro on stackblitz? |
Beta Was this translation helpful? Give feedback.
12 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@1Mouse here you go -> https://stackblitz.com/edit/stackblitz-starters-7xqpvw?file=app%2Flayout.tsx,stores%2FmainStore%2Fprovider.tsx,app%2F_components%2FTestClientComponent.tsx,node_modules%2Fzustand%2Fesm%2Freact.d.mts
The current issue with
createStore
is that doesn't have the api attached to the hook likecreate