function syncEffect()

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;
  };
}