use-persisted-state
Version:
A custom React Hook that provides a multi-instance, multi-tab/browser shared and persistent state.
2 lines (1 loc) • 1.14 kB
JavaScript
import{useRef as e,useState as t,useEffect as l,useCallback as o}from"react";import a from"@use-it/event-listener";const n={},r=(e,t,l)=>(n[e]||(n[e]={callbacks:[],value:l}),n[e].callbacks.push(t),{deregister(){const l=n[e].callbacks,o=l.indexOf(t);o>-1&&l.splice(o,1)},emit(l){n[e].value!==l&&(n[e].value=l,n[e].callbacks.forEach(e=>{t!==e&&e(l)}))}});export default(n,c=(()=>"undefined"!=typeof global&&global.localStorage?global.localStorage:"undefined"!=typeof globalThis&&globalThis.localStorage?globalThis.localStorage:"undefined"!=typeof window&&window.localStorage?window.localStorage:"undefined"!=typeof localStorage?localStorage:null)())=>{if(c){const s=(e=>({get(t,l){const o=e.getItem(t);return null==o?"function"==typeof l?l():l:JSON.parse(o)},set(t,l){e.setItem(t,JSON.stringify(l))}}))(c);return c=>((n,c,{get:s,set:i})=>{const u=e(null),[g,f]=t(()=>s(c,n));a("storage",({key:e,newValue:t})=>{if(e===c){const e=JSON.parse(t);g!==e&&f(e)}}),l(()=>(u.current=r(c,f,n),()=>{u.current.deregister()}),[n,c]);const d=o(e=>{const t="function"==typeof e?e(g):e;i(c,t),f(t),u.current.emit(e)},[g,i,c]);return[g,d]})(c,n,s)}return t};