UNPKG

fluidstate

Version:

Library for fine-grained reactivity state management

92 lines (91 loc) 3.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.observeRemoteAtoms = void 0; var _reactiveLayer = require("./reactive-layer"); var _reactiveRemotesData = require("./reactive-remotes-data"); var _reactiveAction = require("./reactive-action"); var _reactiveNames = require("../extras/reactive-names"); /** * Manages the observation of a local atom (or computed atom) by registered reactive remotes. * * For each reactive remote: * - If the remote is currently tracking (i.e., a reactive computation is active on the remote): * - It ensures a corresponding "remote atom" exists on that remote instance. * - If not, it creates one. This remote atom is linked to the local `layerAtom` * such that changes in the `layerAtom` propagate to the remote atom. * - The creation involves setting up a local reaction that listens to the `layerAtom` * and calls `reportChanged` on the remote atom. This local reaction's scheduling * can be influenced by the `scheduler` provided when the remote was added. * - It then calls `reportObserved()` on this remote atom. * * This function is crucial for establishing a reactive link from a local atom * to its representation on a remote reactive system. * * @param atom - The local atom (or computed atom) being observed. * Used as a key to map to remote atoms. * @param layerAtom - The actual atom (or computed atom) from the underlying reactive layer * that the remote system will effectively listen to. * @param name - The name of the local atom, used for naming the derived remote atom. * @returns `true` if at least one reactive remote observed the atom, `false` otherwise. */ const observeRemoteAtoms = (atom, layerAtom, name) => { let isRemoteObserved = false; let existingRemoteAtoms = _reactiveRemotesData.remoteAtomMap.get(atom); for (const reactiveRemote of _reactiveRemotesData.reactiveRemotes) { let remoteAtom = existingRemoteAtoms?.get(reactiveRemote); if (!remoteAtom && reactiveRemote.isTracking()) { remoteAtom = createRemoteAtom(reactiveRemote, layerAtom, name); if (!existingRemoteAtoms) { existingRemoteAtoms = new WeakMap(); _reactiveRemotesData.remoteAtomMap.set(atom, existingRemoteAtoms); } existingRemoteAtoms.set(reactiveRemote, remoteAtom); } const isCurrentRemoteObserved = !!remoteAtom?.reportObserved(); isRemoteObserved = isRemoteObserved || isCurrentRemoteObserved; } return isRemoteObserved; }; exports.observeRemoteAtoms = observeRemoteAtoms; const createRemoteAtom = (reactiveRemote, layerAtom, name) => { const reactiveOptions = _reactiveRemotesData.remoteOptionsMap.get(reactiveRemote); let isInitialized = false; const localLayer = (0, _reactiveLayer.getReactiveLayer)(); const reaction = localLayer.createReaction(() => { readAtom(layerAtom); if (isInitialized) { localLayer.untrack(() => { (0, _reactiveAction.runRemoteActions)(() => { remoteAtom.reportChanged(); }); }); } }, { scheduler: reactiveOptions?.scheduler }); isInitialized = true; let reactions = _reactiveRemotesData.remoteReactionsMap.get(reactiveRemote); if (!reactions) { reactions = new Set(); _reactiveRemotesData.remoteReactionsMap.set(reactiveRemote, reactions); } reactions.add(reaction); const remoteAtom = reactiveRemote.createAtom((0, _reactiveNames.createRemoteAtomName)(name), { onBecomeUnobservedListener: () => { reaction.stop(); const reactions = _reactiveRemotesData.remoteReactionsMap.get(reactiveRemote); reactions?.delete(reaction); } }); return remoteAtom; }; const readAtom = atom => { if ("reportObserved" in atom) { atom.reportObserved(); } else { atom.get(); } }; //# sourceMappingURL=reactive-remote-atoms.js.map