fluidstate
Version:
Library for fine-grained reactivity state management
92 lines (91 loc) • 3.88 kB
JavaScript
;
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