import { invariant } from "../../utilities/globals/index.js"; import * as React from "rehackt"; import { canUseLayoutEffect } from "../../utilities/index.js"; var didWarnUncachedGetSnapshot = false; // Prevent webpack from complaining about our feature detection of the // useSyncExternalStore property of the React namespace, which is expected not // to exist when using React 17 and earlier, and that's fine. var uSESKey = "useSyncExternalStore"; var realHook = React[uSESKey]; // Adapted from https://www.npmjs.com/package/use-sync-external-store, with // Apollo Client deviations called out by "// DEVIATION ..." comments. // When/if React.useSyncExternalStore is defined, delegate fully to it. export var useSyncExternalStore = realHook || (function (subscribe, getSnapshot, getServerSnapshot) { // Read the current snapshot from the store on every render. Again, this // breaks the rules of React, and only works here because of specific // implementation details, most importantly that updates are // always synchronous. var value = getSnapshot(); if ( // DEVIATION: Using __DEV__ globalThis.__DEV__ !== false && !didWarnUncachedGetSnapshot && // DEVIATION: Not using Object.is because we know our snapshots will never // be exotic primitive values like NaN, which is !== itself. value !== getSnapshot()) { didWarnUncachedGetSnapshot = true; // DEVIATION: Using invariant.error instead of console.error directly. globalThis.__DEV__ !== false && invariant.error(58); } // Because updates are synchronous, we don't queue them. Instead we force a // re-render whenever the subscribed state changes by updating an some // arbitrary useState hook. Then, during render, we call getSnapshot to read // the current value. // // Because we don't actually use the state returned by the useState hook, we // can save a bit of memory by storing other stuff in that slot. // // To implement the early bailout, we need to track some things on a mutable // object. Usually, we would put that in a useRef hook, but we can stash it in // our useState hook instead. // // To force a re-render, we call forceUpdate({inst}). That works because the // new object always fails an equality check. var _a = React.useState({ inst: { value: value, getSnapshot: getSnapshot }, }), inst = _a[0].inst, forceUpdate = _a[1]; // Track the latest getSnapshot function with a ref. This needs to be updated // in the layout phase so we can access it during the tearing check that // happens on subscribe. if (canUseLayoutEffect) { // DEVIATION: We avoid calling useLayoutEffect when !canUseLayoutEffect, // which may seem like a conditional hook, but this code ends up behaving // unconditionally (one way or the other) because canUseLayoutEffect is // constant. React.useLayoutEffect(function () { Object.assign(inst, { value: value, getSnapshot: getSnapshot }); // Whenever getSnapshot or subscribe changes, we need to check in the // commit phase if there was an interleaved mutation. In concurrent mode // this can happen all the time, but even in synchronous mode, an earlier // effect may have mutated the store. if (checkIfSnapshotChanged(inst)) { // Force a re-render. forceUpdate({ inst: inst }); } }, [subscribe, value, getSnapshot]); } else { Object.assign(inst, { value: value, getSnapshot: getSnapshot }); } React.useEffect(function () { // Check for changes right before subscribing. Subsequent changes will be // detected in the subscription handler. if (checkIfSnapshotChanged(inst)) { // Force a re-render. forceUpdate({ inst: inst }); } // Subscribe to the store and return a clean-up function. return subscribe(function handleStoreChange() { // TODO: Because there is no cross-renderer API for batching updates, it's // up to the consumer of this library to wrap their subscription event // with unstable_batchedUpdates. Should we try to detect when this isn't // the case and print a warning in development? // The store changed. Check if the snapshot changed since the last time we // read from the store. if (checkIfSnapshotChanged(inst)) { // Force a re-render. forceUpdate({ inst: inst }); } }); }, [subscribe]); return value; }); function checkIfSnapshotChanged(_a) { var value = _a.value, getSnapshot = _a.getSnapshot; try { return value !== getSnapshot(); } catch (_b) { return true; } } //# sourceMappingURL=useSyncExternalStore.js.map