1 | import { Reaction } from "mobx";
|
2 | import React from "react";
|
3 | import { printDebugValue } from "./utils/printDebugValue";
|
4 | import { isUsingStaticRendering } from "./staticRendering";
|
5 | import { observerFinalizationRegistry } from "./utils/observerFinalizationRegistry";
|
6 | import { useSyncExternalStore } from "use-sync-external-store/shim";
|
7 | function createReaction(adm) {
|
8 | adm.reaction = new Reaction("observer".concat(adm.name), function () {
|
9 | var _a;
|
10 | adm.stateVersion = Symbol();
|
11 | // onStoreChange won't be available until the component "mounts".
|
12 | // If state changes in between initial render and mount,
|
13 | // `useSyncExternalStore` should handle that by checking the state version and issuing update.
|
14 | (_a = adm.onStoreChange) === null || _a === void 0 ? void 0 : _a.call(adm);
|
15 | });
|
16 | }
|
17 | export function useObserver(render, baseComponentName) {
|
18 | if (baseComponentName === void 0) { baseComponentName = "observed"; }
|
19 | if (isUsingStaticRendering()) {
|
20 | return render();
|
21 | }
|
22 | var admRef = React.useRef(null);
|
23 | if (!admRef.current) {
|
24 | // First render
|
25 | var adm_1 = {
|
26 | reaction: null,
|
27 | onStoreChange: null,
|
28 | stateVersion: Symbol(),
|
29 | name: baseComponentName,
|
30 | subscribe: function (onStoreChange) {
|
31 | // Do NOT access admRef here!
|
32 | observerFinalizationRegistry.unregister(adm_1);
|
33 | adm_1.onStoreChange = onStoreChange;
|
34 | if (!adm_1.reaction) {
|
35 | // We've lost our reaction and therefore all subscriptions, occurs when:
|
36 | // 1. Timer based finalization registry disposed reaction before component mounted.
|
37 | // 2. React "re-mounts" same component without calling render in between (typically <StrictMode>).
|
38 | // We have to recreate reaction and schedule re-render to recreate subscriptions,
|
39 | // even if state did not change.
|
40 | createReaction(adm_1);
|
41 | // `onStoreChange` won't force update if subsequent `getSnapshot` returns same value.
|
42 | // So we make sure that is not the case
|
43 | adm_1.stateVersion = Symbol();
|
44 | }
|
45 | return function () {
|
46 | var _a;
|
47 | // Do NOT access admRef here!
|
48 | adm_1.onStoreChange = null;
|
49 | (_a = adm_1.reaction) === null || _a === void 0 ? void 0 : _a.dispose();
|
50 | adm_1.reaction = null;
|
51 | };
|
52 | },
|
53 | getSnapshot: function () {
|
54 | // Do NOT access admRef here!
|
55 | return adm_1.stateVersion;
|
56 | }
|
57 | };
|
58 | admRef.current = adm_1;
|
59 | }
|
60 | var adm = admRef.current;
|
61 | if (!adm.reaction) {
|
62 | // First render or reaction was disposed by registry before subscribe
|
63 | createReaction(adm);
|
64 | // StrictMode/ConcurrentMode/Suspense may mean that our component is
|
65 | // rendered and abandoned multiple times, so we need to track leaked
|
66 | // Reactions.
|
67 | observerFinalizationRegistry.register(admRef, adm, adm);
|
68 | }
|
69 | React.useDebugValue(adm.reaction, printDebugValue);
|
70 | useSyncExternalStore(
|
71 | // Both of these must be stable, otherwise it would keep resubscribing every render.
|
72 | adm.subscribe, adm.getSnapshot, adm.getSnapshot);
|
73 | // render the original component, but have the
|
74 | // reaction track the observables, so that rendering
|
75 | // can be invalidated (see above) once a dependency changes
|
76 | var renderResult;
|
77 | var exception;
|
78 | adm.reaction.track(function () {
|
79 | try {
|
80 | renderResult = render();
|
81 | }
|
82 | catch (e) {
|
83 | exception = e;
|
84 | }
|
85 | });
|
86 | if (exception) {
|
87 | throw exception; // re-throw any exceptions caught during rendering
|
88 | }
|
89 | return renderResult;
|
90 | }
|
91 | //# sourceMappingURL=useObserver.js.map |
\ | No newline at end of file |