Skip to content

Instantly share code, notes, and snippets.

@nico-martin
Last active Nov 22, 2021
Embed
What would you like to do?
A React Context Provider to share State between reloads or even between tabs,
import React from 'react';
import ReactDOM from 'react-dom';
import {
SharedStorageProvider,
useSharedStorage,
} from './sharedStateContext.tsx';
const App = () => {
const [sharedState, setSharedState] = useSharedStorage();
return (
<div>
<p>Current Count: {sharedState.count}</p>
<button
onClick={() =>
setSharedState({
count: sharedState.count + 1,
})
}
>
increase
</button>
</div>
);
};
ReactDOM.render(
<SharedStorageProvider>
<App />
</SharedStorageProvider>,
document.querySelector('#app')
);
import React from 'react';
interface StateI {
[key: string]: any;
}
const Context = React.createContext<{
state: StateI;
setState: (state: StateI) => void;
}>({
state: {},
setState: () => {},
});
export const SharedStorageProvider = ({
children,
storeKey = 'test',
useSessionStorage = false,
}: {
children: any;
storeKey?: string;
useSessionStorage?: boolean;
}) => {
const [store, setStore] = React.useState<StateI>({});
const storage = useSessionStorage ? sessionStorage : localStorage;
React.useEffect(() => {
setStore(getStore());
window.addEventListener('storage', (event) => {
if (event.key === storeKey) {
setStore(getStore());
}
});
}, []);
const getStore = (): StateI =>
JSON.parse(storage.getItem(storeKey)) as StateI;
const updateStore = (part: StateI) => {
const store = getStore();
const newStore = { ...store, ...part };
storage.setItem(storeKey, JSON.stringify(newStore));
setStore(newStore);
};
return (
<Context.Provider value={{ state: store, setState: updateStore }}>
{children}
</Context.Provider>
);
};
export const useSharedStorage = (): [StateI, (state: StateI) => void] => {
const { state, setState } = React.useContext(Context);
return [state, setState];
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment