mobx-react-lite
Version:
Lightweight React bindings for MobX based on React 16.8+ and Hooks
98 lines • 4.39 kB
JavaScript
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
;