Search code examples
reactjsreact-hooksreact-contextzustand

Converting Zustand code to Context API state


I have this piece of code written in typescript for zustand state management library

export 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;
};

how can I convert this piece of code to normal Context API code ?


Solution

  • Create an StoreContext.tsx

    import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
    
    interface StoreContextType<T> {
      state: T;
      setState: React.Dispatch<React.SetStateAction<T>>;
    }
    
    const StoreContext = createContext<StoreContextType<any> | undefined>(undefined);
    
    export const StoreProvider = <T,>({ children, initialState }: { children: ReactNode; initialState: T }) => {
      const [state, setState] = useState<T>(initialState);
    
      return (
        <StoreContext.Provider value={{ state, setState }}>
          {children}
        </StoreContext.Provider>
      );
    };
    

    create a custom hook

    export const useStore = <T, F>(callback: (state: T) => F): F => {
      const context = useContext(StoreContext);
    
      if (!context) {
        throw new Error('useStore must be used within a StoreProvider');
      }
    
      const { state, setState } = context as StoreContextType<T>;
      const [data, setData] = useState<F>();
    
      useEffect(() => {
        const result = callback(state);
        setData(result);
      }, [state, callback]);
    
      return data as F;
    };
    

    wrap the index file with store provider

    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import { StoreProvider, initialState, AppState } from './StoreContext';
    
    ReactDOM.render(
      <React.StrictMode>
        <StoreProvider<AppState> initialState={initialState}>
          <App />
        </StoreProvider>
      </React.StrictMode>,
      document.getElementById('root')
    );
    

    use the context in your relevant componenet

    type AppState = {
      count: number;
    };
    
    const initialState: AppState = {
      count: 0,
    };
    
    const MyComponent = () => {
      const count = useStore((state: AppState) => state.count);
    
      return <div>Count: {count}</div>;
    };