UNPKG

mobx-react-lite

Version:

Lightweight React bindings for MobX based on React 16.8+ and Hooks

98 lines 4.39 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.useObserver = void 0; var mobx_1 = require("mobx"); var react_1 = __importDefault(require("react")); var printDebugValue_1 = require("./utils/printDebugValue"); var staticRendering_1 = require("./staticRendering"); var observerFinalizationRegistry_1 = require("./utils/observerFinalizationRegistry"); var shim_1 = require("use-sync-external-store/shim"); function createReaction(adm) { adm.reaction = new mobx_1.Reaction("observer".concat(adm.name), function () { var _a; adm.stateVersion = Symbol(); // onStoreChange won't be available until the component "mounts". // If state changes in between initial render and mount, // `useSyncExternalStore` should handle that by checking the state version and issuing update. (_a = adm.onStoreChange) === null || _a === void 0 ? void 0 : _a.call(adm); }); } function useObserver(render, baseComponentName) { if (baseComponentName === void 0) { baseComponentName = "observed"; } if ((0, staticRendering_1.isUsingStaticRendering)()) { return render(); } var admRef = react_1.default.useRef(null); if (!admRef.current) { // First render var adm_1 = { reaction: null, onStoreChange: null, stateVersion: Symbol(), name: baseComponentName, subscribe: function (onStoreChange) { // Do NOT access admRef here! observerFinalizationRegistry_1.observerFinalizationRegistry.unregister(adm_1); adm_1.onStoreChange = onStoreChange; if (!adm_1.reaction) { // We've lost our reaction and therefore all subscriptions, occurs when: // 1. Timer based finalization registry disposed reaction before component mounted. // 2. React "re-mounts" same component without calling render in between (typically <StrictMode>). // We have to recreate reaction and schedule re-render to recreate subscriptions, // even if state did not change. createReaction(adm_1); // `onStoreChange` won't force update if subsequent `getSnapshot` returns same value. // So we make sure that is not the case adm_1.stateVersion = Symbol(); } return function () { var _a; // Do NOT access admRef here! adm_1.onStoreChange = null; (_a = adm_1.reaction) === null || _a === void 0 ? void 0 : _a.dispose(); adm_1.reaction = null; }; }, getSnapshot: function () { // Do NOT access admRef here! return adm_1.stateVersion; } }; admRef.current = adm_1; } var adm = admRef.current; if (!adm.reaction) { // First render or reaction was disposed by registry before subscribe createReaction(adm); // StrictMode/ConcurrentMode/Suspense may mean that our component is // rendered and abandoned multiple times, so we need to track leaked // Reactions. observerFinalizationRegistry_1.observerFinalizationRegistry.register(admRef, adm, adm); } react_1.default.useDebugValue(adm.reaction, printDebugValue_1.printDebugValue); (0, shim_1.useSyncExternalStore)( // Both of these must be stable, otherwise it would keep resubscribing every render. adm.subscribe, adm.getSnapshot, adm.getSnapshot); // render the original component, but have the // reaction track the observables, so that rendering // can be invalidated (see above) once a dependency changes var renderResult; var exception; adm.reaction.track(function () { try { renderResult = render(); } catch (e) { exception = e; } }); if (exception) { throw exception; // re-throw any exceptions caught during rendering } return renderResult; } exports.useObserver = useObserver; //# sourceMappingURL=useObserver.js.map