in packages/recoil/core/Recoil_RecoilRoot.js [157:202]
function sendEndOfBatchNotifications(store: Store) {
const storeState = store.getState();
const treeState = storeState.currentTree;
// Inform transaction subscribers of the transaction:
const dirtyAtoms = treeState.dirtyAtoms;
if (dirtyAtoms.size) {
// Execute Node-specific subscribers before global subscribers
for (const [
key,
subscriptions,
] of storeState.nodeTransactionSubscriptions) {
if (dirtyAtoms.has(key)) {
for (const [_, subscription] of subscriptions) {
subscription(store);
}
}
}
for (const [_, subscription] of storeState.transactionSubscriptions) {
subscription(store);
}
if (!reactMode().early || storeState.suspendedComponentResolvers.size > 0) {
// Notifying components is needed to wake from suspense, even when using
// early rendering.
notifyComponents(store, storeState, treeState);
// Wake all suspended components so the right one(s) can try to re-render.
// We need to wake up components not just when some asynchronous selector
// resolved, but also when changing synchronous values because this may cause
// a selector to change from asynchronous to synchronous, in which case there
// would be no follow-up asynchronous resolution to wake us up.
// TODO OPTIMIZATION Only wake up related downstream components
storeState.suspendedComponentResolvers.forEach(cb => cb());
storeState.suspendedComponentResolvers.clear();
}
}
// Special behavior ONLY invoked by useInterface.
// FIXME delete queuedComponentCallbacks_DEPRECATED when deleting useInterface.
storeState.queuedComponentCallbacks_DEPRECATED.forEach(cb => cb(treeState));
storeState.queuedComponentCallbacks_DEPRECATED.splice(
0,
storeState.queuedComponentCallbacks_DEPRECATED.length,
);
}