in packages/recoil-sync/RecoilSync.js [519:595]
function syncEffect<T>(opt: SyncEffectOptions<T>): AtomEffect<T> {
return ({node, trigger, storeID, setSelf, getLoadable, getInfo_UNSTABLE}) => {
// Get options with defaults
const itemKey = opt.itemKey ?? node.key;
const options: AtomSyncOptions<T> = {
itemKey,
read: ({read}) => read(itemKey),
write: ({write}, loadable) => write(itemKey, loadable),
syncDefault: false,
actionOnFailure_UNSTABLE: 'errorState',
...opt,
};
const {storeKey} = options;
const storage = registries.getStorage(storeID, storeKey);
// Register Atom
const {effectRegistration, unregisterEffect} = registries.setAtomEffect(
storeID,
storeKey,
node,
options,
);
if (trigger === 'get') {
// Initialize Atom value
const readFromStorage = storage?.read;
if (readFromStorage != null) {
try {
const loadable = readAtomItems(effectRegistration, readFromStorage);
if (loadable != null) {
switch (loadable.state) {
case 'hasValue':
if (!(loadable.contents instanceof DefaultValue)) {
setSelf(loadable.contents);
}
break;
case 'hasError':
if (options.actionOnFailure_UNSTABLE === 'errorState') {
throw loadable.contents;
}
break;
case 'loading':
setSelf(loadable.toPromise());
break;
}
}
} catch (error) {
if (options.actionOnFailure_UNSTABLE === 'errorState') {
throw error;
}
}
}
// Persist on Initial Read
const writeToStorage = storage?.write;
if (options.syncDefault === true && writeToStorage != null) {
setImmediate(() => {
const loadable = getLoadable(node);
if (loadable.state === 'hasValue') {
const diff = writeAtomItemsToDiff(
new Map(),
options,
storage?.read,
loadable,
);
writeToStorage(
getWriteInterface(storeID, storeKey, diff, getInfo_UNSTABLE),
);
}
});
}
}
// Cleanup atom effect registration
return unregisterEffect;
};
}