UNPKG

@zedux/atoms

Version:

A Molecular State Engine for React

79 lines (78 loc) 3.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.injectEffect = void 0; const createInjector_1 = require("../factories/createInjector"); const index_1 = require("../utils/index"); const getTask = (effect, descriptor) => { const task = () => { const cleanup = effect(); // now that the task has run, there's no need for the scheduler cleanup // function; replace it with the cleanup logic returned from the effect // (if any). If a promise was returned, ignore it. descriptor.cleanup = typeof cleanup === 'function' ? cleanup : undefined; }; return task; }; /** * Runs a deferred side effect. This is just like React's `useEffect`. When * `deps` change on a subsequent reevaluation, the previous effect will be * cleaned up and the effect will rerun. * * Return a cleanup function to clean up resources when the effect reruns or the * current atom instance is destroyed. * * Unlike `useEffect`, you can return a promise from `injectEffect` (e.g. by * passing an async function). This is only for convenience in cases where you * don't have anything to cleanup, as you'll be unable to clean up resources if * you return a promise. */ exports.injectEffect = (0, createInjector_1.createInjector)('injectEffect', (instance, effect, deps, config) => { const descriptor = { deps, type: `${index_1.prefix}/effect`, }; if (!instance.ecosystem.ssr) { const task = getTask(effect, descriptor); descriptor.cleanup = () => { instance.ecosystem._scheduler.unschedule(task); descriptor.cleanup = undefined; }; if (config === null || config === void 0 ? void 0 : config.synchronous) { task(); } else { instance.ecosystem._scheduler.schedule({ task, type: 4, // RunEffect (4) }); } } return descriptor; }, (prevDescriptor, instance, effect, deps, config) => { var _a; if (instance.ecosystem.ssr) return prevDescriptor; const depsHaveChanged = (0, index_1.haveDepsChanged)(prevDescriptor === null || prevDescriptor === void 0 ? void 0 : prevDescriptor.deps, deps); if (!depsHaveChanged) return prevDescriptor; (_a = prevDescriptor.cleanup) === null || _a === void 0 ? void 0 : _a.call(prevDescriptor); const task = getTask(effect, prevDescriptor); // this cleanup should be unnecessary since effects run immediately every // time except init. Leave this though in case we add a way to update an // atom instance without flushing the scheduler prevDescriptor.cleanup = () => { instance.ecosystem._scheduler.unschedule(task); prevDescriptor.cleanup = undefined; }; prevDescriptor.deps = deps; if (config === null || config === void 0 ? void 0 : config.synchronous) { task(); } else { instance.ecosystem._scheduler.schedule({ task, type: 4, // RunEffect (4) }); } return prevDescriptor; });