Skip to content

Instantly share code, notes, and snippets.

@WomB0ComB0
Created January 19, 2025 16:19
Show Gist options
  • Save WomB0ComB0/3da1cb2ebfe8fb48a80a9adfcc21d2cb to your computer and use it in GitHub Desktop.
Save WomB0ComB0/3da1cb2ebfe8fb48a80a9adfcc21d2cb to your computer and use it in GitHub Desktop.
GlobalStoreProvider component that provides the global store to the React component tree. This component initializes the store on first render and maintains a consistent reference to it using useRef to prevent unnecessary re-renders.
'use client';
import { type StoreState, createGlobalStore } from '@/core/store';
import type React from 'react';
import { createContext, useContext, useRef } from 'react';
import { useStore } from 'zustand';
/**
* React context to provide the global store throughout the application. The context
* holds a reference to the store created by createGlobalStore or null if not yet initialized.
*
* @type {React.Context<ReturnType<typeof createGlobalStore> | null>}
*/
const GlobalStoreContext = createContext<ReturnType<typeof createGlobalStore> | null>(null);
/**
* GlobalStoreProvider component that provides the global store to the React component tree.
* This component initializes the store on first render and maintains a consistent reference
* to it using useRef to prevent unnecessary re-renders.
*
* @component
* @param {object} props - Component props
* @param {React.ReactNode} props.children - Child components that will have access to the global store
* @returns {React.JSX.Element} GlobalStoreProvider component wrapping the children with the store context
* @example
* ```tsx
* <GlobalStoreProvider>
* <App />
* </GlobalStoreProvider>
* ```
*/
export const GlobalStoreProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
const storeRef = useRef<ReturnType<typeof createGlobalStore>>(createGlobalStore());
if (!storeRef.current) {
storeRef.current = createGlobalStore();
}
return (
<GlobalStoreContext.Provider value={storeRef.current}>{children}</GlobalStoreContext.Provider>
);
};
/**
* Custom hook to access and select data from the global store.
* This hook must be used within a component that is wrapped by GlobalStoreProvider.
*
* @template T The type of the selected state slice
* @param {function} selector - Selector function that extracts and returns the desired state slice
* @param {StoreState} selector.state - The complete store state object
* @returns {T} The selected state slice
* @throws {Error} If used outside of a GlobalStoreProvider
* @example
* ```tsx
* const userName = useGlobalStore((state) => state.user.name);
* const userAge = useGlobalStore((state) => state.user.age);
* ```
*/
export const useGlobalStore = <T,>(selector: (state: StoreState) => T) => {
const store = useContext(GlobalStoreContext);
if (!store) {
throw new Error('useGlobalStore must be used within a GlobalStoreProvider');
}
return useStore(store, selector);
};
@WomB0ComB0
Copy link
Author

import { createStore } from 'zustand';

/**
 * Interface representing the global store state.
 * @interface StoreState
 */
interface StoreState {
   /** FAQ section containing accordion state */
  faq: {
    /** Index of currently open FAQ item */
    openIndex: number | null;
    /** Sets the open FAQ item index */
    setOpenIndex: (value: number | null) => void;
    /** Toggles an FAQ item open/closed */
    toggleOpen: (index: number) => void;
  };
}
/**
 * Creates a global store using Zustand for state management.
 * Initializes header and map state with default values and setter functions.
 *
 * @function createGlobalStore
 * @returns {StoreApi<StoreState>} The initialized Zustand store
 *
 * @example
 * const store = createGlobalStore();
 * store.getState().header.setIsMenuOpen(true);
 * store.getState().map.toggleFilter('Active');
 */
const createGlobalStore = () =>
  createStore<StoreState>((set) => ({
      faq: {
      openIndex: null as number | null,
      setOpenIndex: (value: number | null) =>
        set((state) => ({
          faq: { ...state.faq, openIndex: value },
        })),
      toggleOpen: (index: number) =>
        set((state) => ({
          faq: {
            ...state.faq,
            openIndex: state.faq.openIndex === index ? null : index,
          },
        })),
    },
  }))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment