UNPKG

@methodjs/store

Version:

Store for React Functional Componets

283 lines (277 loc) 9.26 kB
import { __assign } from 'tslib'; import { useState, useEffect } from 'react'; import { createBehavior as createBehavior$1 } from '..'; function createSetValueCallback(key, setValueCallbackArray) { return function (value, payload) { setValueCallbackArray.forEach(function (_a) { var test = _a.test, behavior = _a.behavior; if (test(key)) { behavior(value, key, payload); } }); }; } function createUpdateInformation(key, updateInformationArray) { return function (information, value) { updateInformationArray.forEach(function (_a) { var test = _a.test, behavior = _a.behavior; if (test(key)) { behavior(information, value); } }); }; } function createBehaviorStore() { var setValueCallbackArray = []; var updateInformationArray = []; function getBehavior(key) { return { setValueCallback: createSetValueCallback(key, setValueCallbackArray), updateInformation: createUpdateInformation(key, updateInformationArray), }; } function createBehavior(test, behavior) { var isAlive = false; var nextTest = function (key) { if (isAlive) { return test(key); } return false; }; if (behavior.setValueCallback !== undefined) { setValueCallbackArray.push({ test: nextTest, behavior: behavior.setValueCallback, }); } if (behavior.updateInformation !== undefined) { updateInformationArray.push({ test: nextTest, behavior: behavior.updateInformation, }); } function startBehavior() { isAlive = true; } function stopBehavior() { isAlive = false; } return [startBehavior, stopBehavior]; } return { getBehavior: getBehavior, createBehavior: createBehavior }; } var _a = createBehaviorStore(), getBehavior = _a.getBehavior, createBehavior = _a.createBehavior; var INITIALIZE = 'INITIALIZE'; function isSetValueAction(next) { if (typeof next === 'function') { return true; } return false; } function isSetValueWithMapperAction(next) { if (typeof next === 'function') { return true; } return false; } function isCreateStoreOptionWithMapper(option) { if (option !== undefined && option.mapper !== undefined) { return true; } return false; } function isLazyIntializedValue(next) { if (typeof next === 'function') { return true; } return false; } function createStore(initialValue, option) { var current; var key = (option === null || option === void 0 ? void 0 : option.key) || "store-".concat(Math.random()); var onValueSet = new Set(); var activatedHookIdSet = new Set(); var information = { key: key, transactionId: 0, activated: false, updated: null, payload: null, }; function getIntializedValue() { if (isLazyIntializedValue(initialValue)) { return initialValue(); } else { return initialValue; } } function updateInformation(next, value) { information = __assign(__assign({}, information), next); var behavior = getBehavior(key); behavior.updateInformation(information, value); } var getValue = function getValue() { if (current === undefined) { current = getIntializedValue(); updateInformation({ transactionId: information.transactionId + 1, updated: new Date(), payload: { action: INITIALIZE }, }, current); return current; } else { return current; } }; function subscribe(onValue) { onValueSet.add(onValue); function unsubscribe() { if (onValueSet.has(onValue)) { onValueSet.delete(onValue); } } return unsubscribe; } function useValue() { var _a = useState(getValue), state = _a[0], setState = _a[1]; useEffect(function () { function onValue() { var nextState = getValue(); setState(nextState); } // Hook 가 mount 되는 동안, 변경된 값으로 갱신한다. onValue(); var unsubscribe = subscribe(onValue); return unsubscribe; }, []); useEffect(function () { var id = "Hook-".concat(Date.now()); activatedHookIdSet.add(id); updateInformation({ activated: true }, getValue()); return function () { activatedHookIdSet.delete(id); if (activatedHookIdSet.size === 0) { updateInformation({ activated: false }, getValue()); } }; }, []); return state; } function setValueCallback(payload) { onValueSet.forEach(function (onValue) { return onValue(); }); updateInformation({ transactionId: information.transactionId + 1, updated: new Date(), payload: payload || null, }, getValue()); var behavior = getBehavior(key); behavior.setValueCallback(getValue(), payload); } if (isCreateStoreOptionWithMapper(option)) { var mapper_1 = option.mapper; var setValue = function setValue(next, payload) { var pre = getValue(); if (isSetValueWithMapperAction(next)) { current = mapper_1(next(pre), pre, payload); } else { current = mapper_1(next, pre, payload); } setValueCallback(payload); }; return [useValue, setValue, getValue]; } else { var setValue = function setValue(next, payload) { if (isSetValueAction(next)) { current = next(getValue()); } else { current = next; } setValueCallback(payload); }; return [useValue, setValue, getValue]; } } function createQuery(query, keys) { var onValueSet = new Set(); function test(key) { return keys.includes(key); } function setValueCallback() { onValueSet.forEach(function (onValue) { return onValue(); }); } var startBehavior = createBehavior$1(test, { setValueCallback: setValueCallback })[0]; function subscribe(onValue) { onValueSet.add(onValue); function unsubscribe() { if (onValueSet.has(onValue)) { onValueSet.delete(onValue); } } return unsubscribe; } function useView() { var _a = useState(query()), state = _a[0], setState = _a[1]; useEffect(function () { startBehavior(); function onValue() { setState(query()); } var unsubscribe = subscribe(onValue); return unsubscribe; }, []); return state; } return useView; } function createAsyncQuery(asyncQuery, keys) { var onValueSet = new Set(); function test(key) { return keys.includes(key); } function setValueCallback() { onValueSet.forEach(function (onValue) { return onValue(); }); } var startBehavior = createBehavior$1(test, { setValueCallback: setValueCallback })[0]; function subscribe(onValue) { onValueSet.add(onValue); function unsubscribe() { if (onValueSet.has(onValue)) { onValueSet.delete(onValue); } } return unsubscribe; } function useView() { var _a = useState(), state = _a[0], setState = _a[1]; useEffect(function () { Promise.resolve(asyncQuery()).then(setState); startBehavior(); function onValue() { Promise.resolve(asyncQuery()).then(setState); } var unsubscribe = subscribe(onValue); return unsubscribe; }, []); return state; } return useView; } function createDevToolsBehavior(test) { var updateInformation = function (information, value) { var _a; if (((_a = window.__METHODJS_DEV_TOOLS_WORKER__) === null || _a === void 0 ? void 0 : _a.updateStoreInformation) !== undefined) { window.__METHODJS_DEV_TOOLS_WORKER__.updateStoreInformation(information, value); } }; var nextTest = test === undefined ? function () { return true; } : test; return createBehavior(nextTest, { updateInformation: updateInformation, }); } export { createAsyncQuery, createBehavior, createDevToolsBehavior, createQuery, createStore };