function RecoilRoot_INTERNAL()

in packages/recoil/core/Recoil_RecoilRoot.js [353:527]


function RecoilRoot_INTERNAL({
  initializeState_DEPRECATED,
  initializeState,
  store_INTERNAL: storeProp, // For use with React "context bridging"
  children,
}: InternalProps): React.Node {
  // prettier-ignore
  // @fb-only: useEffect(() => {
    // @fb-only: if (gkx('recoil_usage_logging')) {
      // @fb-only: try {
        // @fb-only: RecoilUsageLogFalcoEvent.log(() => ({
          // @fb-only: type: RecoilusagelogEvent.RECOIL_ROOT_MOUNTED,
          // @fb-only: path: URI.getRequestURI().getPath(),
        // @fb-only: }));
      // @fb-only: } catch {
        // @fb-only: recoverableViolation(
          // @fb-only: 'Error when logging Recoil Usage event',
          // @fb-only: 'recoil',
        // @fb-only: );
      // @fb-only: }
    // @fb-only: }
  // @fb-only: }, []);

  let storeStateRef: {current: StoreState}; // eslint-disable-line prefer-const

  const getGraph = version => {
    const graphs = storeStateRef.current.graphsByVersion;
    if (graphs.has(version)) {
      return nullthrows(graphs.get(version));
    }
    const newGraph = graph();
    graphs.set(version, newGraph);
    return newGraph;
  };

  const subscribeToTransactions = (callback, key) => {
    if (key == null) {
      // Global transaction subscriptions
      const {transactionSubscriptions} = storeRef.current.getState();
      const id = nextID++;
      transactionSubscriptions.set(id, callback);
      return {
        release: () => {
          transactionSubscriptions.delete(id);
        },
      };
    } else {
      // Node-specific transaction subscriptions:
      const {nodeTransactionSubscriptions} = storeRef.current.getState();
      if (!nodeTransactionSubscriptions.has(key)) {
        nodeTransactionSubscriptions.set(key, new Map());
      }
      const id = nextID++;
      nullthrows(nodeTransactionSubscriptions.get(key)).set(id, callback);
      return {
        release: () => {
          const subs = nodeTransactionSubscriptions.get(key);
          if (subs) {
            subs.delete(id);
            if (subs.size === 0) {
              nodeTransactionSubscriptions.delete(key);
            }
          }
        },
      };
    }
  };

  const addTransactionMetadata = (metadata: {...}) => {
    startNextTreeIfNeeded(storeRef.current);
    for (const k of Object.keys(metadata)) {
      nullthrows(storeRef.current.getState().nextTree).transactionMetadata[k] =
        metadata[k];
    }
  };

  const replaceState = replacer => {
    startNextTreeIfNeeded(storeRef.current);
    // Use replacer to get the next state:
    const nextTree = nullthrows(storeStateRef.current.nextTree);
    let replaced;
    try {
      stateReplacerIsBeingExecuted = true;
      replaced = replacer(nextTree);
    } finally {
      stateReplacerIsBeingExecuted = false;
    }
    if (replaced === nextTree) {
      return;
    }

    if (__DEV__) {
      if (typeof window !== 'undefined') {
        window.$recoilDebugStates.push(replaced); // TODO this shouldn't happen here because it's not batched
      }
    }

    // Save changes to nextTree and schedule a React update:
    storeStateRef.current.nextTree = replaced;
    if (reactMode().early) {
      notifyComponents(storeRef.current, storeStateRef.current, replaced);
    }
    nullthrows(notifyBatcherOfChange.current)();
  };

  const notifyBatcherOfChange = useRef<null | (mixed => void)>(null);
  const setNotifyBatcherOfChange = useCallback(
    (x: mixed => void) => {
      notifyBatcherOfChange.current = x;
    },
    [notifyBatcherOfChange],
  );

  const storeRef = useRefInitOnce(
    () =>
      storeProp ?? {
        storeID: getNextStoreID(),
        getState: () => storeStateRef.current,
        replaceState,
        getGraph,
        subscribeToTransactions,
        addTransactionMetadata,
      },
  );
  if (storeProp != null) {
    storeRef.current = storeProp;
  }

  storeStateRef = useRefInitOnce(() =>
    initializeState_DEPRECATED != null
      ? initialStoreState_DEPRECATED(
          storeRef.current,
          initializeState_DEPRECATED,
        )
      : initializeState != null
      ? initialStoreState(initializeState)
      : makeEmptyStoreState(),
  );

  const mutableSource = useMemo(
    () =>
      createMutableSource?.(
        storeStateRef,
        () => storeStateRef.current.currentTree.version,
      ),
    [storeStateRef],
  );

  // Cleanup when the <RecoilRoot> is unmounted
  useEffect(() => {
    // React is free to call effect cleanup handlers and effects at will, the
    // deps array is only an optimization.  For example, React strict mode
    // will execute each effect twice for testing.  Therefore, we need symmetry
    // to re-initialize all known atoms after they were cleaned up.
    const store = storeRef.current;
    for (const atomKey of new Set(store.getState().knownAtoms)) {
      initializeNode(store, atomKey, 'get');
    }

    return () => {
      for (const atomKey of store.getState().knownAtoms) {
        cleanUpNode(store, atomKey);
      }
    };
  }, [storeRef]);

  return (
    <AppContext.Provider value={storeRef}>
      <MutableSourceContext.Provider value={mutableSource}>
        <Batcher setNotifyBatcherOfChange={setNotifyBatcherOfChange} />
        {children}
      </MutableSourceContext.Provider>
    </AppContext.Provider>
  );
}