UNPKG

react-tienda

Version:

React Tienda is a lightweight and intuitive global state management library for React, designed to easily share state across components with minimal setup.

140 lines (136 loc) 5.41 kB
import { isObject, EventBus, includeKeys, joinObjects, has } from 'hd-utils'; import React, { useState, useCallback, useMemo } from 'react'; function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } // In case the react version doesn't support useLayoutEffect var useEffect = React.useLayoutEffect || React.useEffect; function newObjWithKeys(keyList, mappedToObj) { var newObj = {}; keyList.forEach(function (key) { newObj[key] = mappedToObj[key]; }); return newObj; } var UPDATE_STATE_EVENT = 'UPDATE_STATE'; /** * @description Will create a global store where state is shared among components that use the returned hook that can be used to set and get the state. * @advanced You can enter the global (store scope) state using useStore.getGlobalState() or set the global state useStore.setGlobalState * @author https://github.com/AhmadHddad * @example export const useStore = createGlobalStore({a:1, b:2}); * @returns hook that is used to connect the component with the store. * its its really recommended to specify the used store keys in the returned hook (as list of strings) to reduce the component rerendering. * @example const Component = () => { * const [storeState, setStoreState] = useStore(["a"]); * * return <button onClick={()=> setStoreState({a:3})}>Click me</button> * } */ function createGlobalStore(initState, actions, storeConfigs) { if (initState === void 0) { initState = {}; } if (actions === void 0) { actions = {}; } if (!isObject(initState)) { throw new Error('Error: The initial state should be of type object'); } var oldState = _extends({}, initState); var storeState = _extends({}, initState); var storeBus = new EventBus(); function useStore(select, hookConfigs) { var _ref = hookConfigs || {}, shallowCompareOnSetState = _ref.shallowCompareOnSetState; var _useState = useState(Array.isArray(select) ? newObjWithKeys(select, storeState) : storeState), componentState = _useState[0], setComponentState = _useState[1]; var shallowCompare = shallowCompareOnSetState != null ? shallowCompareOnSetState : storeConfigs == null ? void 0 : storeConfigs.shallowCompareOnSetState; useEffect(function () { var handleStateChange = function handleStateChange(updatedState) { var newState = {}; for (var key in updatedState) { if (has(componentState, key)) { newState[key] = updatedState[key]; } } if (Object.keys(newState).length === 0) { return; } storeState = joinObjects(storeState, newState); setComponentState(function (prev) { return _extends({}, prev, newState); }); }; storeBus.subscribe(UPDATE_STATE_EVENT, handleStateChange); return function () { storeBus.unsubscribe(UPDATE_STATE_EVENT, handleStateChange); }; }, []); var updateState = useCallback(function (newState, options) { if (typeof newState === 'function') { var updatedState = newState(componentState); if (!isObject(updatedState)) { throw new Error('Error: The return type should be object with the new state'); } storeBus.publish(UPDATE_STATE_EVENT, updatedState); } else { if (!isObject(newState)) { throw new Error('Error: The updated state should be of type object or function'); } var isEqual = (options == null ? void 0 : options.comparer) && options.comparer(componentState, newState); if (isEqual) { return; } if (shallowCompare) { var keyList = select || Object.keys(componentState); keyList.forEach(function (key) { if (componentState[key] === newState[key]) { delete newState[key]; } }); } storeBus.publish(UPDATE_STATE_EVENT, newState); } }, [componentState, select, shallowCompare]); var resetStoreState = useCallback(function (all) { var newState = !all && select ? includeKeys(oldState, select) : oldState; storeBus.publish(UPDATE_STATE_EVENT, newState); }, [select]); var actionsMemo = useMemo(function () { var newActions = {}; for (var actionKey in actions) { if (Object.prototype.hasOwnProperty.call(actions, actionKey)) { var action = actions[actionKey]; newActions[actionKey] = action(storeState, updateState); } } return newActions; }, [actions, updateState]); return [componentState, useMemo(function () { return { setStoreState: updateState, actions: actionsMemo, resetStoreState: resetStoreState }; }, [actionsMemo, resetStoreState])]; } useStore.setGlobalState = function (newState, options) { if (options != null && options.override) { storeState = joinObjects(storeState, newState); } storeBus.publish(UPDATE_STATE_EVENT, newState); }; useStore.getGlobalState = function () { return storeState; }; return useStore; } export default createGlobalStore; //# sourceMappingURL=react-tienda.esm.js.map