Skip to content

Instantly share code, notes, and snippets.

@j2is
Created June 30, 2021 10:59
Show Gist options
  • Save j2is/51a780dbeeeb42152b29f8ef61c54b87 to your computer and use it in GitHub Desktop.
Save j2is/51a780dbeeeb42152b29f8ef61c54b87 to your computer and use it in GitHub Desktop.
Immer state management
import React, { useState, useMemo, useContext } from "react";
import immer from "immer";
export default function makeStore() {
// This is basically a factory for a new store instance
const loggerActive = false;
// Create a new context for this store instance
const context = React.createContext();
// Make a provider that takes an initial state
const Provider = ({ children, initialState = {} }) => {
// useImmer will do
const [state, setState] = useState(initialState);
const immerSetState = updater => {
// if (loggerActive) console.log('STORE UPDATE');
setState(old => {
// if (loggerActive) console.log('before:', old);
// if (loggerActive) console.log('updater:', updater);
const next = immer(old, updater);
// if (loggerActive) console.log('after:', next);
return next;
});
};
// Memoize the context value so it only updates when the state changes
const contextValue = useMemo(() => [state, immerSetState], [state]);
// Pass the context down
return <context.Provider value={contextValue}>{children}</context.Provider>;
};
// A hook to consume the context. No need to import `useContext` everywhere. How wasteful...
const useStore = () => useContext(context);
// Export them however you like. I prefer a default.
return {
Provider,
useStore
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment