azux
Version:
A small state management that is inspired on unstated-next
1 lines • 1.8 kB
JavaScript
import{createContext,useRef,useEffect,createElement,useContext,useState}from"react";const defaultSelector=e=>e;let extendStore;export function Provider({store:e,children:t,initial:r}){return"function"!=typeof e?Array.isArray(e)?e.reduceRight((e,[t,r])=>_Provider(t,r,e),t):Object.entries(e).reduceRight((e,[t,o])=>_Provider(o,r?r[t]:void 0,e),t):_Provider(e,r,t)};function makeSureProviderCreated(e){e.__context||(e.__context=createContext())}function _Provider(e,t,r){makeSureProviderCreated(e);const o=useRef(void 0);if(!o.current){const e=[];o.current={parents:new WeakMap,subscribe:t=>(e.push(t),function(){const r=e.indexOf(t);e.splice(r,1)}),dispatch(){e.forEach(e=>e())}}}let n=extendStore;const c=[];try{extendStore=function(e,t){makeSureProviderCreated(e);let r=o.current.parents.get(e);r||(r={subscribe:o.current.subscribe},o.current.parents.get(e,r)),r.api=e(t),c.push([e.__context,r])},o.current.api=e(t),c.unshift([e.__context,o.current])}finally{extendStore=n}return useEffect(()=>{o.current.dispatch()}),c.reduceRight((e,t)=>createElement(t[0].Provider,{value:t[1],children:e}),r)}export function useStore(){return extendStore?extendStore(...arguments):_useStore(...arguments)};function createSelector(e,t,r){return e===r&&t?t:null===e||void 0===e?defaultSelector:"function"==typeof e?e:t=>t[e]}function _useStore(e,t){if(!e.__context)throw new Error("No store context found");const[,r]=useState(),o=useRef({}).current,n=useContext(e.__context);return useEffect(()=>n.subscribe(()=>{const e=o.selector(n.api);e===o.prev||"object"==typeof e&&"object"==typeof o.prev&&Object.keys(e).concat(Object.keys(o.prev)).every(t=>e[t]===o.prev[t])||r({})}),[n,o]),o.selector=createSelector(t,o.selector,o.originalSelector),o.originalSelector=t,o.prev="function"==typeof t?t(n.api):n.api,o.prev}