Next.js Discord

Discord Forum

Nextjs and Zustand (outside react component)

Unanswered
Silky ant posted this in #help-forum
Open in Discord
Silky antOP
Hi, can I use a Zustand store Hi, how can I use a Zustand store outside of a React component in Next.js 15? I can't find any examples in the documentation.


export type ExampleStoreProps = {
  enableDevtools?: boolean;
  initState: ExampleStoreState;
};

export type ExampleStoreApi = t_StoreApi<ExampleStore, boolean>;

export const createExampleStore = ({
  enableDevtools = false,
  initState: _initState,
}: ExampleStoreProps) => {
  const initState = _initState;

  const stateCreator = (set: any, get, store): ExampleStore => ({
    ...(initState as any),
    setExampleProp: (path: string[], value: any) => {
      return set((state: ExampleStoreState) =>
        produce(state, (draft) => {
          _.set(draft.example._config, path, {
            ...(_.get(draft.example._config, path) || {}),
            ...value,
          });
        })
      );
    },

    getExampleProp: (path: string[]) => {
      const state = get();
      return _.get(state.example._config, path);
    },
  });

  let res = null as any;

  if (enableDevtools) {
    res = createStore(devtools(stateCreator, { name: "ExampleStore", enabled: enableDevtools }));
  } else {
    res = createStore(stateCreator);
  }

  return res as ExampleStoreApi;
};

6 Replies

Silky antOP
export const ExampleContext = createContext<ExampleContextProps | null>(null);

export type ExampleProviderProps = Pick<ExampleStoreProps, "initState">;

export const ExampleProvider = ({
  children,
  initState,
}: PropsWithChildren & ExampleProviderProps) => {
  const enableDevtools = false as const;
  const exampleStoreRef = useRef<ExampleStoreApi | null>(null);
  if (!exampleStoreRef.current) {
    exampleStoreRef.current = createExampleStore({ enableDevtools, initState });
  }

  return (
    <ExampleContext.Provider value={exampleStoreRef.current}>
      {children}
    </ExampleContext.Provider>
  );
};

export const useExampleContext = <T,>(
  selector: (state: ExampleStore) => T
): T => {
  const store = useContext(ExampleContext) as ExampleStoreApi | null;
  if (!store) {
    console.error("ExampleContext is missing. Ensure you are within an ExampleProvider.");
    throw new Error("useExampleContext must be used within an ExampleProvider");
  }

  return useStore(store, selector);
};
Roseate Spoonbill
Yes, you can. Stores have two ways of being created - with createStore (without react utils attached) and create which is both react hook and the actual store.

Both expose store-related functionality, including getState() method which you can call wherever to access the store and it's data and functions.
Take a look at https://zustand.docs.pmnd.rs/apis/create-store#updating-state-based-on-previous-state - there are examples of how the store can be used from inside addEventListener callback, without react context at all.
@Roseate Spoonbill Yes, you can. Stores have two ways of being created - with `createStore` (without react utils attached) and `create` which is both react hook and the actual store. Both expose store-related functionality, including `getState()` method which you can call wherever to access the store and it's data and functions.
Silky antOP
Thank you very much for your response ,

I would like to keep this approach but make it accessible in a way other than through the provider. So I did this:

if (!exampleStoreRef.current) {
  const store = createExampleStore({ enableDevtools, initState });

  exampleStoreRef.current = store;
  externalExampleStoreInstance = store;
}


And later I use const { ... } = externalExampleStoreInstance.getState() inside a function that's outside of React components.
I don't know if it's correct — I haven't tested it, but I find it a bit weird
Roseate Spoonbill
I've seen people assigning stores to ref whenever the store is not supposed to be global. If your state store can be or is global, you don't need ref at all. You can create store and export it directly outside of react component.
IMHO you need ref or context for sharing store only if your store is localized and can have multiple instances going at the same time