mobx-react 7.6.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,54 +1,28 @@
1
- import { _allowStateReadsStart, _allowStateReadsEnd, $mobx, _allowStateChanges, createAtom, Reaction, untracked, isObservableMap, isObservableObject, isObservableArray, observable } from 'mobx';
1
+ import { createAtom, _allowStateReadsStart, _allowStateReadsEnd, Reaction, _allowStateChanges, untracked, isObservableMap, isObservableObject, isObservableArray, observable } from 'mobx';
2
2
  import React__default, { PureComponent, Component } from 'react';
3
- import { isUsingStaticRendering, observer as observer$1 } from 'mobx-react-lite';
3
+ import { isUsingStaticRendering, _observerFinalizationRegistry, observer as observer$1 } from 'mobx-react-lite';
4
4
  export { Observer, enableStaticRendering, isUsingStaticRendering, observerBatching, useAsObservableSource, useLocalObservable, useLocalStore, useObserver, useStaticRendering } from 'mobx-react-lite';
5
5
 
6
- var symbolId = 0;
7
-
8
- function createSymbol(name) {
9
- if (typeof Symbol === "function") {
10
- return Symbol(name);
11
- }
12
-
13
- var symbol = "__$mobx-react " + name + " (" + symbolId + ")";
14
- symbolId++;
15
- return symbol;
16
- }
17
-
18
- var createdSymbols = {};
19
- function newSymbol(name) {
20
- if (!createdSymbols[name]) {
21
- createdSymbols[name] = createSymbol(name);
22
- }
23
-
24
- return createdSymbols[name];
25
- }
26
6
  function shallowEqual(objA, objB) {
27
7
  //From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
28
8
  if (is(objA, objB)) {
29
9
  return true;
30
10
  }
31
-
32
11
  if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
33
12
  return false;
34
13
  }
35
-
36
14
  var keysA = Object.keys(objA);
37
15
  var keysB = Object.keys(objB);
38
-
39
16
  if (keysA.length !== keysB.length) {
40
17
  return false;
41
18
  }
42
-
43
19
  for (var i = 0; i < keysA.length; i++) {
44
20
  if (!Object.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
45
21
  return false;
46
22
  }
47
23
  }
48
-
49
24
  return true;
50
25
  }
51
-
52
26
  function is(x, y) {
53
27
  // From: https://github.com/facebook/fbjs/blob/c69904a511b900266935168223063dd8772dfc40/packages/fbjs/src/core/shallowEqual.js
54
28
  if (x === y) {
@@ -56,9 +30,8 @@ function is(x, y) {
56
30
  } else {
57
31
  return x !== x && y !== y;
58
32
  }
59
- } // based on https://github.com/mridgway/hoist-non-react-statics/blob/master/src/index.js
60
-
61
-
33
+ }
34
+ // based on https://github.com/mridgway/hoist-non-react-statics/blob/master/src/index.js
62
35
  var hoistBlackList = {
63
36
  $$typeof: 1,
64
37
  render: 1,
@@ -83,33 +56,12 @@ function copyStaticProperties(base, target) {
83
56
  }
84
57
  });
85
58
  }
86
- /**
87
- * Helper to set `prop` to `this` as non-enumerable (hidden prop)
88
- * @param target
89
- * @param prop
90
- * @param value
91
- */
92
-
93
- function setHiddenProp(target, prop, value) {
94
- if (!Object.hasOwnProperty.call(target, prop)) {
95
- Object.defineProperty(target, prop, {
96
- enumerable: false,
97
- configurable: true,
98
- writable: true,
99
- value: value
100
- });
101
- } else {
102
- target[prop] = value;
103
- }
104
- }
105
59
  /**
106
60
  * Utilities for patching componentWillUnmount, to make sure @disposeOnUnmount works correctly icm with user defined hooks
107
61
  * and the handler provided by mobx-react
108
62
  */
109
-
110
- var mobxMixins = /*#__PURE__*/newSymbol("patchMixins");
111
- var mobxPatchedDefinition = /*#__PURE__*/newSymbol("patchedDefinition");
112
-
63
+ var mobxMixins = /*#__PURE__*/Symbol("patchMixins");
64
+ var mobxPatchedDefinition = /*#__PURE__*/Symbol("patchedDefinition");
113
65
  function getMixins(target, methodName) {
114
66
  var mixins = target[mobxMixins] = target[mobxMixins] || {};
115
67
  var methodMixins = mixins[methodName] = mixins[methodName] || {};
@@ -117,28 +69,21 @@ function getMixins(target, methodName) {
117
69
  methodMixins.methods = methodMixins.methods || [];
118
70
  return methodMixins;
119
71
  }
120
-
121
72
  function wrapper(realMethod, mixins) {
122
73
  var _this = this;
123
-
124
74
  for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
125
75
  args[_key - 2] = arguments[_key];
126
76
  }
127
-
128
77
  // locks are used to ensure that mixins are invoked only once per invocation, even on recursive calls
129
78
  mixins.locks++;
130
-
131
79
  try {
132
80
  var retVal;
133
-
134
81
  if (realMethod !== undefined && realMethod !== null) {
135
82
  retVal = realMethod.apply(this, args);
136
83
  }
137
-
138
84
  return retVal;
139
85
  } finally {
140
86
  mixins.locks--;
141
-
142
87
  if (mixins.locks === 0) {
143
88
  mixins.methods.forEach(function (mx) {
144
89
  mx.apply(_this, args);
@@ -146,41 +91,31 @@ function wrapper(realMethod, mixins) {
146
91
  }
147
92
  }
148
93
  }
149
-
150
94
  function wrapFunction(realMethod, mixins) {
151
95
  var fn = function fn() {
152
96
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
153
97
  args[_key2] = arguments[_key2];
154
98
  }
155
-
156
99
  wrapper.call.apply(wrapper, [this, realMethod, mixins].concat(args));
157
100
  };
158
-
159
101
  return fn;
160
102
  }
161
-
162
103
  function patch(target, methodName, mixinMethod) {
163
104
  var mixins = getMixins(target, methodName);
164
-
165
105
  if (mixins.methods.indexOf(mixinMethod) < 0) {
166
106
  mixins.methods.push(mixinMethod);
167
107
  }
168
-
169
108
  var oldDefinition = Object.getOwnPropertyDescriptor(target, methodName);
170
-
171
109
  if (oldDefinition && oldDefinition[mobxPatchedDefinition]) {
172
110
  // already patched definition, do not repatch
173
111
  return;
174
112
  }
175
-
176
113
  var originalMethod = target[methodName];
177
114
  var newDefinition = createDefinition(target, methodName, oldDefinition ? oldDefinition.enumerable : undefined, mixins, originalMethod);
178
115
  Object.defineProperty(target, methodName, newDefinition);
179
116
  }
180
-
181
117
  function createDefinition(target, methodName, enumerable, mixins, originalMethod) {
182
118
  var _ref;
183
-
184
119
  var wrappedFunc = wrapFunction(originalMethod, mixins);
185
120
  return _ref = {}, _ref[mobxPatchedDefinition] = true, _ref.get = function get() {
186
121
  return wrappedFunc;
@@ -198,247 +133,231 @@ function createDefinition(target, methodName, enumerable, mixins, originalMethod
198
133
  }, _ref.configurable = true, _ref.enumerable = enumerable, _ref;
199
134
  }
200
135
 
201
- var mobxAdminProperty = $mobx || "$mobx"; // BC
202
-
203
- var mobxObserverProperty = /*#__PURE__*/newSymbol("isMobXReactObserver");
204
- var mobxIsUnmounted = /*#__PURE__*/newSymbol("isUnmounted");
205
- var skipRenderKey = /*#__PURE__*/newSymbol("skipRender");
206
- var isForcingUpdateKey = /*#__PURE__*/newSymbol("isForcingUpdate");
136
+ var administrationSymbol = /*#__PURE__*/Symbol("ObserverAdministration");
137
+ var isMobXReactObserverSymbol = /*#__PURE__*/Symbol("isMobXReactObserver");
138
+ function getAdministration(component) {
139
+ var _component$administra;
140
+ // We create administration lazily, because we can't patch constructor
141
+ // and the exact moment of initialization partially depends on React internals.
142
+ // At the time of writing this, the first thing invoked is one of the observable getter/setter (state/props/context).
143
+ return (_component$administra = component[administrationSymbol]) != null ? _component$administra : component[administrationSymbol] = {
144
+ reaction: null,
145
+ mounted: false,
146
+ forceUpdate: null,
147
+ name: getDisplayName(component.constructor),
148
+ state: undefined,
149
+ props: undefined,
150
+ context: undefined,
151
+ propsAtom: createAtom("props"),
152
+ stateAtom: createAtom("state"),
153
+ contextAtom: createAtom("context"),
154
+ isUpdating: false
155
+ };
156
+ }
207
157
  function makeClassComponentObserver(componentClass) {
208
- var target = componentClass.prototype;
209
-
210
- if (componentClass[mobxObserverProperty]) {
211
- var displayName = getDisplayName(target);
158
+ var prototype = componentClass.prototype;
159
+ if (componentClass[isMobXReactObserverSymbol]) {
160
+ var displayName = getDisplayName(componentClass);
212
161
  console.warn("The provided component class (" + displayName + ")\n has already been declared as an observer component.");
213
162
  } else {
214
- componentClass[mobxObserverProperty] = true;
163
+ componentClass[isMobXReactObserverSymbol] = true;
215
164
  }
216
-
217
- if (target.componentWillReact) {
165
+ if (prototype.componentWillReact) {
218
166
  throw new Error("The componentWillReact life-cycle event is no longer supported");
219
167
  }
220
-
221
168
  if (componentClass["__proto__"] !== PureComponent) {
222
- if (!target.shouldComponentUpdate) {
223
- target.shouldComponentUpdate = observerSCU;
224
- } else if (target.shouldComponentUpdate !== observerSCU) {
169
+ if (!prototype.shouldComponentUpdate) {
170
+ prototype.shouldComponentUpdate = observerSCU;
171
+ } else if (prototype.shouldComponentUpdate !== observerSCU) {
225
172
  // n.b. unequal check, instead of existence check, as @observer might be on superclass as well
226
173
  throw new Error("It is not allowed to use shouldComponentUpdate in observer based components.");
227
174
  }
228
- } // this.props and this.state are made observable, just to make sure @computed fields that
175
+ }
176
+ // this.props and this.state are made observable, just to make sure @computed fields that
229
177
  // are defined inside the component, and which rely on state or props, re-compute if state or props change
230
178
  // (otherwise the computed wouldn't update and become stale on props change, since props are not observable)
231
179
  // However, this solution is not without it's own problems: https://github.com/mobxjs/mobx-react/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Aobservable-props-or-not+
232
-
233
-
234
- makeObservableProp(target, "props");
235
- makeObservableProp(target, "state");
236
-
237
- if (componentClass.contextType) {
238
- makeObservableProp(target, "context");
239
- }
240
-
241
- var originalRender = target.render;
242
-
180
+ Object.defineProperties(prototype, {
181
+ props: observablePropsDescriptor,
182
+ state: observableStateDescriptor,
183
+ context: observableContextDescriptor
184
+ });
185
+ var originalRender = prototype.render;
243
186
  if (typeof originalRender !== "function") {
244
- var _displayName = getDisplayName(target);
245
-
187
+ var _displayName = getDisplayName(componentClass);
246
188
  throw new Error("[mobx-react] class component (" + _displayName + ") is missing `render` method." + "\n`observer` requires `render` being a function defined on prototype." + "\n`render = () => {}` or `render = function() {}` is not supported.");
247
189
  }
248
-
249
- target.render = function () {
250
- this.render = isUsingStaticRendering() ? originalRender : createReactiveRender.call(this, originalRender);
190
+ prototype.render = function () {
191
+ Object.defineProperty(this, "render", {
192
+ // There is no safe way to replace render, therefore it's forbidden.
193
+ configurable: false,
194
+ writable: false,
195
+ value: isUsingStaticRendering() ? originalRender : createReactiveRender.call(this, originalRender)
196
+ });
251
197
  return this.render();
252
198
  };
253
-
254
- patch(target, "componentDidMount", function () {
255
- this[mobxIsUnmounted] = false;
256
-
257
- if (!this.render[mobxAdminProperty]) {
258
- // Reaction is re-created automatically during render, but a component can re-mount and skip render #3395.
259
- // To re-create the reaction and re-subscribe to relevant observables we have to force an update.
260
- Component.prototype.forceUpdate.call(this);
199
+ patch(prototype, "componentDidMount", function () {
200
+ var _this = this;
201
+ // `componentDidMount` may not be called at all. React can abandon the instance after `render`.
202
+ // That's why we use finalization registry to dispose reaction created during render.
203
+ // Happens with `<Suspend>` see #3492
204
+ //
205
+ // `componentDidMount` can be called immediately after `componentWillUnmount` without calling `render` in between.
206
+ // Happens with `<StrictMode>`see #3395.
207
+ //
208
+ // If `componentDidMount` is called, it's guaranteed to run synchronously with render (similary to `useLayoutEffect`).
209
+ // Therefore we don't have to worry about external (observable) state being updated before mount (no state version checking).
210
+ //
211
+ // Things may change: "In the future, React will provide a feature that lets components preserve state between unmounts"
212
+ var admin = getAdministration(this);
213
+ admin.mounted = true;
214
+ // Component instance committed, prevent reaction disposal.
215
+ _observerFinalizationRegistry.unregister(admin);
216
+ // We don't set forceUpdate before mount because it requires a reference to `this`,
217
+ // therefore `this` could NOT be garbage collected before mount,
218
+ // preventing reaction disposal by FinalizationRegistry and leading to memory leak.
219
+ // As an alternative we could have `admin.instanceRef = new WeakRef(this)`, but lets avoid it if possible.
220
+ admin.forceUpdate = function () {
221
+ return _this.forceUpdate();
222
+ };
223
+ if (!admin.reaction) {
224
+ // 1. Instance was unmounted (reaction disposed) and immediately remounted without running render #3395.
225
+ // 2. Reaction was disposed by finalization registry before mount. Shouldn't ever happen for class components:
226
+ // `componentDidMount` runs synchronously after render, but our registry are deferred (can't run in between).
227
+ // In any case we lost subscriptions to observables, so we have to create new reaction and re-render to resubscribe.
228
+ // The reaction will be created lazily by following render.
229
+ admin.forceUpdate();
261
230
  }
262
231
  });
263
- patch(target, "componentWillUnmount", function () {
232
+ patch(prototype, "componentWillUnmount", function () {
233
+ var _admin$reaction;
264
234
  if (isUsingStaticRendering()) {
265
235
  return;
266
236
  }
267
-
268
- var reaction = this.render[mobxAdminProperty];
269
-
270
- if (reaction) {
271
- reaction.dispose(); // Forces reaction to be re-created on next render
272
-
273
- this.render[mobxAdminProperty] = null;
274
- } else {
275
- // Render may have been hot-swapped and/or overridden by a subclass.
276
- var _displayName2 = getDisplayName(this);
277
-
278
- console.warn("The reactive render of an observer class component (" + _displayName2 + ")\n was overridden after MobX attached. This may result in a memory leak if the\n overridden reactive render was not properly disposed.");
279
- }
280
-
281
- this[mobxIsUnmounted] = true;
237
+ var admin = getAdministration(this);
238
+ (_admin$reaction = admin.reaction) == null ? void 0 : _admin$reaction.dispose();
239
+ admin.reaction = null;
240
+ admin.forceUpdate = null;
241
+ admin.mounted = false;
282
242
  });
283
243
  return componentClass;
284
- } // Generates a friendly name for debugging
285
-
286
- function getDisplayName(comp) {
287
- return comp.displayName || comp.name || comp.constructor && (comp.constructor.displayName || comp.constructor.name) || "<component>";
288
244
  }
289
-
245
+ // Generates a friendly name for debugging
246
+ function getDisplayName(componentClass) {
247
+ return componentClass.displayName || componentClass.name || "<component>";
248
+ }
290
249
  function createReactiveRender(originalRender) {
291
- var _this = this;
292
-
293
- /**
294
- * If props are shallowly modified, react will render anyway,
295
- * so atom.reportChanged() should not result in yet another re-render
296
- */
297
- setHiddenProp(this, skipRenderKey, false);
298
- /**
299
- * forceUpdate will re-assign this.props. We don't want that to cause a loop,
300
- * so detect these changes
301
- */
302
-
303
- setHiddenProp(this, isForcingUpdateKey, false);
304
- var initialName = getDisplayName(this);
305
250
  var boundOriginalRender = originalRender.bind(this);
306
- var isRenderingPending = false;
307
-
308
- var createReaction = function createReaction() {
309
- var reaction = new Reaction(initialName + ".render()", function () {
310
- if (!isRenderingPending) {
311
- // N.B. Getting here *before mounting* means that a component constructor has side effects (see the relevant test in misc.test.tsx)
312
- // This unidiomatic React usage but React will correctly warn about this so we continue as usual
313
- // See #85 / Pull #44
314
- isRenderingPending = true;
315
-
316
- if (_this[mobxIsUnmounted] !== true) {
317
- var hasError = true;
318
-
319
- try {
320
- setHiddenProp(_this, isForcingUpdateKey, true);
321
-
322
- if (!_this[skipRenderKey]) {
323
- Component.prototype.forceUpdate.call(_this);
324
- }
325
-
326
- hasError = false;
327
- } finally {
328
- setHiddenProp(_this, isForcingUpdateKey, false);
329
-
330
- if (hasError) {
331
- reaction.dispose(); // Forces reaction to be re-created on next render
332
-
333
- _this.render[mobxAdminProperty] = null;
334
- }
335
- }
336
- }
337
- }
338
- });
339
- reaction["reactComponent"] = _this;
340
- return reaction;
341
- };
342
-
251
+ var admin = getAdministration(this);
343
252
  function reactiveRender() {
344
- var _reactiveRender$mobxA;
345
-
346
- isRenderingPending = false; // Create reaction lazily to support re-mounting #3395
347
-
348
- var reaction = (_reactiveRender$mobxA = reactiveRender[mobxAdminProperty]) != null ? _reactiveRender$mobxA : reactiveRender[mobxAdminProperty] = createReaction();
349
- var exception = undefined;
350
- var rendering = undefined;
351
- reaction.track(function () {
253
+ if (!admin.reaction) {
254
+ // Create reaction lazily to support re-mounting #3395
255
+ admin.reaction = createReaction(admin);
256
+ if (!admin.mounted) {
257
+ // React can abandon this instance and never call `componentDidMount`/`componentWillUnmount`,
258
+ // we have to make sure reaction will be disposed.
259
+ _observerFinalizationRegistry.register(this, admin, this);
260
+ }
261
+ }
262
+ var error = undefined;
263
+ var renderResult = undefined;
264
+ admin.reaction.track(function () {
352
265
  try {
353
266
  // TODO@major
354
267
  // Optimization: replace with _allowStateChangesStart/End (not available in mobx@6.0.0)
355
- rendering = _allowStateChanges(false, boundOriginalRender);
268
+ renderResult = _allowStateChanges(false, boundOriginalRender);
356
269
  } catch (e) {
357
- exception = e;
270
+ error = e;
358
271
  }
359
272
  });
360
-
361
- if (exception) {
362
- throw exception;
273
+ if (error) {
274
+ throw error;
363
275
  }
364
-
365
- return rendering;
276
+ return renderResult;
366
277
  }
367
-
368
278
  return reactiveRender;
369
279
  }
370
-
280
+ function createReaction(admin) {
281
+ return new Reaction(admin.name + ".render()", function () {
282
+ if (admin.isUpdating) {
283
+ // Reaction is suppressed when setting new state/props/context,
284
+ // this is when component is already being updated.
285
+ return;
286
+ }
287
+ if (!admin.mounted) {
288
+ // This is neccessary to avoid react warning about calling forceUpdate on component that isn't mounted yet.
289
+ // This happens when component is abandoned after render - our reaction is already created and reacts to changes.
290
+ // Due to the synchronous nature of `componenDidMount`, we don't have to worry that component could eventually mount and require update.
291
+ return;
292
+ }
293
+ try {
294
+ // forceUpdate sets new `props`, since we made it observable, it would `reportChanged`, causing a loop.
295
+ admin.isUpdating = true;
296
+ admin.forceUpdate == null ? void 0 : admin.forceUpdate();
297
+ } catch (error) {
298
+ var _admin$reaction2;
299
+ (_admin$reaction2 = admin.reaction) == null ? void 0 : _admin$reaction2.dispose();
300
+ admin.reaction = null;
301
+ } finally {
302
+ admin.isUpdating = false;
303
+ }
304
+ });
305
+ }
371
306
  function observerSCU(nextProps, nextState) {
372
307
  if (isUsingStaticRendering()) {
373
308
  console.warn("[mobx-react] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side.");
374
- } // update on any state changes (as is the default)
375
-
376
-
309
+ }
310
+ // update on any state changes (as is the default)
377
311
  if (this.state !== nextState) {
378
312
  return true;
379
- } // update if props are shallowly not equal, inspired by PureRenderMixin
313
+ }
314
+ // update if props are shallowly not equal, inspired by PureRenderMixin
380
315
  // we could return just 'false' here, and avoid the `skipRender` checks etc
381
316
  // however, it is nicer if lifecycle events are triggered like usually,
382
317
  // so we return true here if props are shallowly modified.
383
-
384
-
385
318
  return !shallowEqual(this.props, nextProps);
386
319
  }
387
-
388
- function makeObservableProp(target, propName) {
389
- var valueHolderKey = newSymbol("reactProp_" + propName + "_valueHolder");
390
- var atomHolderKey = newSymbol("reactProp_" + propName + "_atomHolder");
391
-
392
- function getAtom() {
393
- if (!this[atomHolderKey]) {
394
- setHiddenProp(this, atomHolderKey, createAtom("reactive " + propName));
395
- }
396
-
397
- return this[atomHolderKey];
398
- }
399
-
400
- Object.defineProperty(target, propName, {
320
+ function createObservablePropDescriptor(key) {
321
+ var atomKey = key + "Atom";
322
+ return {
401
323
  configurable: true,
402
324
  enumerable: true,
403
325
  get: function get() {
404
- var prevReadState = false; // Why this check? BC?
405
- // @ts-expect-error
406
-
407
- if (_allowStateReadsStart && _allowStateReadsEnd) {
408
- prevReadState = _allowStateReadsStart(true);
409
- }
410
-
411
- getAtom.call(this).reportObserved(); // Why this check? BC?
412
- // @ts-expect-error
413
-
414
- if (_allowStateReadsStart && _allowStateReadsEnd) {
415
- _allowStateReadsEnd(prevReadState);
416
- }
417
-
418
- return this[valueHolderKey];
326
+ var admin = getAdministration(this);
327
+ var prevReadState = _allowStateReadsStart(true);
328
+ admin[atomKey].reportObserved();
329
+ _allowStateReadsEnd(prevReadState);
330
+ return admin[key];
419
331
  },
420
- set: function set(v) {
421
- if (!this[isForcingUpdateKey] && !shallowEqual(this[valueHolderKey], v)) {
422
- setHiddenProp(this, valueHolderKey, v);
423
- setHiddenProp(this, skipRenderKey, true);
424
- getAtom.call(this).reportChanged();
425
- setHiddenProp(this, skipRenderKey, false);
332
+ set: function set(value) {
333
+ var admin = getAdministration(this);
334
+ // forceUpdate issued by reaction sets new props.
335
+ // It sets isUpdating to true to prevent loop.
336
+ if (!admin.isUpdating && !shallowEqual(admin[key], value)) {
337
+ admin[key] = value;
338
+ // This notifies all observers including our component,
339
+ // but we don't want to cause `forceUpdate`, because component is already updating,
340
+ // therefore supress component reaction.
341
+ admin.isUpdating = true;
342
+ admin[atomKey].reportChanged();
343
+ admin.isUpdating = false;
426
344
  } else {
427
- setHiddenProp(this, valueHolderKey, v);
345
+ admin[key] = value;
428
346
  }
429
347
  }
430
- });
348
+ };
431
349
  }
350
+ var observablePropsDescriptor = /*#__PURE__*/createObservablePropDescriptor("props");
351
+ var observableStateDescriptor = /*#__PURE__*/createObservablePropDescriptor("state");
352
+ var observableContextDescriptor = /*#__PURE__*/createObservablePropDescriptor("context");
432
353
 
433
354
  /**
434
355
  * Observer function / decorator
435
356
  */
436
-
437
357
  function observer(component) {
438
358
  if (component["isMobxInjector"] === true) {
439
359
  console.warn("Mobx observer: You are trying to use `observer` on a component that already has `inject`. Please apply `observer` before applying `inject`");
440
360
  }
441
-
442
361
  if (Object.prototype.isPrototypeOf.call(Component, component) || Object.prototype.isPrototypeOf.call(PureComponent, component)) {
443
362
  // Class component
444
363
  return makeClassComponentObserver(component);
@@ -449,35 +368,29 @@ function observer(component) {
449
368
  }
450
369
 
451
370
  function _extends() {
452
- _extends = Object.assign || function (target) {
371
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
453
372
  for (var i = 1; i < arguments.length; i++) {
454
373
  var source = arguments[i];
455
-
456
374
  for (var key in source) {
457
375
  if (Object.prototype.hasOwnProperty.call(source, key)) {
458
376
  target[key] = source[key];
459
377
  }
460
378
  }
461
379
  }
462
-
463
380
  return target;
464
381
  };
465
-
466
382
  return _extends.apply(this, arguments);
467
383
  }
468
-
469
384
  function _objectWithoutPropertiesLoose(source, excluded) {
470
385
  if (source == null) return {};
471
386
  var target = {};
472
387
  var sourceKeys = Object.keys(source);
473
388
  var key, i;
474
-
475
389
  for (i = 0; i < sourceKeys.length; i++) {
476
390
  key = sourceKeys[i];
477
391
  if (excluded.indexOf(key) >= 0) continue;
478
392
  target[key] = source[key];
479
393
  }
480
-
481
394
  return target;
482
395
  }
483
396
 
@@ -485,21 +398,16 @@ var _excluded = ["children"];
485
398
  var MobXProviderContext = /*#__PURE__*/React__default.createContext({});
486
399
  function Provider(props) {
487
400
  var children = props.children,
488
- stores = _objectWithoutPropertiesLoose(props, _excluded);
489
-
401
+ stores = _objectWithoutPropertiesLoose(props, _excluded);
490
402
  var parentValue = React__default.useContext(MobXProviderContext);
491
403
  var mutableProviderRef = React__default.useRef(_extends({}, parentValue, stores));
492
404
  var value = mutableProviderRef.current;
493
-
494
405
  {
495
406
  var newValue = _extends({}, value, stores); // spread in previous state for the context based stores
496
-
497
-
498
407
  if (!shallowEqual(value, newValue)) {
499
408
  throw new Error("MobX Provider: The set of provided stores has changed. See: https://github.com/mobxjs/mobx-react#the-set-of-provided-stores-has-changed-error.");
500
409
  }
501
410
  }
502
-
503
411
  return React__default.createElement(MobXProviderContext.Provider, {
504
412
  value: value
505
413
  }, children);
@@ -509,38 +417,31 @@ Provider.displayName = "MobXProvider";
509
417
  /**
510
418
  * Store Injection
511
419
  */
512
-
513
420
  function createStoreInjector(grabStoresFn, component, injectNames, makeReactive) {
514
421
  // Support forward refs
515
422
  var Injector = React__default.forwardRef(function (props, ref) {
516
423
  var newProps = _extends({}, props);
517
-
518
424
  var context = React__default.useContext(MobXProviderContext);
519
425
  Object.assign(newProps, grabStoresFn(context || {}, newProps) || {});
520
-
521
426
  if (ref) {
522
427
  newProps.ref = ref;
523
428
  }
524
-
525
429
  return React__default.createElement(component, newProps);
526
430
  });
527
431
  if (makeReactive) Injector = observer(Injector);
528
432
  Injector["isMobxInjector"] = true; // assigned late to suppress observer warning
529
433
  // Static fields from component should be visible on the generated Injector
530
-
531
434
  copyStaticProperties(component, Injector);
532
435
  Injector["wrappedComponent"] = component;
533
436
  Injector.displayName = getInjectName(component, injectNames);
534
437
  return Injector;
535
438
  }
536
-
537
439
  function getInjectName(component, injectNames) {
538
440
  var displayName;
539
441
  var componentName = component.displayName || component.name || component.constructor && component.constructor.name || "Component";
540
442
  if (injectNames) displayName = "inject-with-" + injectNames + "(" + componentName + ")";else displayName = "inject(" + componentName + ")";
541
443
  return displayName;
542
444
  }
543
-
544
445
  function grabStoresByName(storeNames) {
545
446
  return function (baseStores, nextProps) {
546
447
  storeNames.forEach(function (storeName) {
@@ -558,13 +459,10 @@ function grabStoresByName(storeNames) {
558
459
  * or a function that manually maps the available stores from the context to props:
559
460
  * storesToProps(mobxStores, props, context) => newProps
560
461
  */
561
-
562
-
563
462
  function inject() {
564
463
  for (var _len = arguments.length, storeNames = new Array(_len), _key = 0; _key < _len; _key++) {
565
464
  storeNames[_key] = arguments[_key];
566
465
  }
567
-
568
466
  if (typeof arguments[0] === "function") {
569
467
  var grabStoresFn = arguments[0];
570
468
  return function (componentClass) {
@@ -577,14 +475,14 @@ function inject() {
577
475
  }
578
476
  }
579
477
 
580
- var protoStoreKey = /*#__PURE__*/newSymbol("disposeOnUnmountProto");
581
- var instStoreKey = /*#__PURE__*/newSymbol("disposeOnUnmountInst");
582
-
478
+ var reactMajorVersion = /*#__PURE__*/Number.parseInt( /*#__PURE__*/React__default.version.split(".")[0]);
479
+ var warnedAboutDisposeOnUnmountDeprecated = false;
480
+ var protoStoreKey = /*#__PURE__*/Symbol("disposeOnUnmountProto");
481
+ var instStoreKey = /*#__PURE__*/Symbol("disposeOnUnmountInst");
583
482
  function runDisposersOnWillUnmount() {
584
483
  var _this = this;
585
484
  [].concat(this[protoStoreKey] || [], this[instStoreKey] || []).forEach(function (propKeyOrFunction) {
586
485
  var prop = typeof propKeyOrFunction === "string" ? _this[propKeyOrFunction] : propKeyOrFunction;
587
-
588
486
  if (prop !== undefined && prop !== null) {
589
487
  if (Array.isArray(prop)) prop.map(function (f) {
590
488
  return f();
@@ -592,62 +490,67 @@ function runDisposersOnWillUnmount() {
592
490
  }
593
491
  });
594
492
  }
595
-
493
+ /**
494
+ * @deprecated `disposeOnUnmount` is not compatible with React 18 and higher.
495
+ */
596
496
  function disposeOnUnmount(target, propertyKeyOrFunction) {
597
497
  if (Array.isArray(propertyKeyOrFunction)) {
598
498
  return propertyKeyOrFunction.map(function (fn) {
599
499
  return disposeOnUnmount(target, fn);
600
500
  });
601
501
  }
602
-
502
+ if (!warnedAboutDisposeOnUnmountDeprecated) {
503
+ if (reactMajorVersion >= 18) {
504
+ console.error("[mobx-react] disposeOnUnmount is not compatible with React 18 and higher. Don't use it.");
505
+ } else {
506
+ console.warn("[mobx-react] disposeOnUnmount is deprecated. It won't work correctly with React 18 and higher.");
507
+ }
508
+ warnedAboutDisposeOnUnmountDeprecated = true;
509
+ }
603
510
  var c = Object.getPrototypeOf(target).constructor;
604
- var c2 = Object.getPrototypeOf(target.constructor); // Special case for react-hot-loader
605
-
511
+ var c2 = Object.getPrototypeOf(target.constructor);
512
+ // Special case for react-hot-loader
606
513
  var c3 = Object.getPrototypeOf(Object.getPrototypeOf(target));
607
-
608
514
  if (!(c === React__default.Component || c === React__default.PureComponent || c2 === React__default.Component || c2 === React__default.PureComponent || c3 === React__default.Component || c3 === React__default.PureComponent)) {
609
515
  throw new Error("[mobx-react] disposeOnUnmount only supports direct subclasses of React.Component or React.PureComponent.");
610
516
  }
611
-
612
517
  if (typeof propertyKeyOrFunction !== "string" && typeof propertyKeyOrFunction !== "function" && !Array.isArray(propertyKeyOrFunction)) {
613
518
  throw new Error("[mobx-react] disposeOnUnmount only works if the parameter is either a property key or a function.");
614
- } // decorator's target is the prototype, so it doesn't have any instance properties like props
615
-
616
-
617
- var isDecorator = typeof propertyKeyOrFunction === "string"; // add property key / function we want run (disposed) to the store
618
-
519
+ }
520
+ // decorator's target is the prototype, so it doesn't have any instance properties like props
521
+ var isDecorator = typeof propertyKeyOrFunction === "string";
522
+ // add property key / function we want run (disposed) to the store
619
523
  var componentWasAlreadyModified = !!target[protoStoreKey] || !!target[instStoreKey];
620
- var store = isDecorator ? // decorators are added to the prototype store
621
- target[protoStoreKey] || (target[protoStoreKey] = []) : // functions are added to the instance store
524
+ var store = isDecorator ?
525
+ // decorators are added to the prototype store
526
+ target[protoStoreKey] || (target[protoStoreKey] = []) :
527
+ // functions are added to the instance store
622
528
  target[instStoreKey] || (target[instStoreKey] = []);
623
- store.push(propertyKeyOrFunction); // tweak the component class componentWillUnmount if not done already
624
-
529
+ store.push(propertyKeyOrFunction);
530
+ // tweak the component class componentWillUnmount if not done already
625
531
  if (!componentWasAlreadyModified) {
626
532
  patch(target, "componentWillUnmount", runDisposersOnWillUnmount);
627
- } // return the disposer as is if invoked as a non decorator
628
-
629
-
533
+ }
534
+ // return the disposer as is if invoked as a non decorator
630
535
  if (typeof propertyKeyOrFunction !== "string") {
631
536
  return propertyKeyOrFunction;
632
537
  }
633
538
  }
634
539
 
540
+ // Copied from React.PropTypes
635
541
  function createChainableTypeChecker(validator) {
636
542
  function checkType(isRequired, props, propName, componentName, location, propFullName) {
637
543
  for (var _len = arguments.length, rest = new Array(_len > 6 ? _len - 6 : 0), _key = 6; _key < _len; _key++) {
638
544
  rest[_key - 6] = arguments[_key];
639
545
  }
640
-
641
546
  return untracked(function () {
642
547
  componentName = componentName || "<<anonymous>>";
643
548
  propFullName = propFullName || propName;
644
-
645
549
  if (props[propName] == null) {
646
550
  if (isRequired) {
647
551
  var actual = props[propName] === null ? "null" : "undefined";
648
552
  return new Error("The " + location + " `" + propFullName + "` is marked as required " + "in `" + componentName + "`, but its value is `" + actual + "`.");
649
553
  }
650
-
651
554
  return null;
652
555
  } else {
653
556
  // @ts-ignore rest arg is necessary for some React internals - fails tests otherwise
@@ -655,60 +558,48 @@ function createChainableTypeChecker(validator) {
655
558
  }
656
559
  });
657
560
  }
658
-
659
- var chainedCheckType = checkType.bind(null, false); // Add isRequired to satisfy Requirable
660
-
561
+ var chainedCheckType = checkType.bind(null, false);
562
+ // Add isRequired to satisfy Requirable
661
563
  chainedCheckType.isRequired = checkType.bind(null, true);
662
564
  return chainedCheckType;
663
- } // Copied from React.PropTypes
664
-
665
-
565
+ }
566
+ // Copied from React.PropTypes
666
567
  function isSymbol(propType, propValue) {
667
568
  // Native Symbol.
668
569
  if (propType === "symbol") {
669
570
  return true;
670
- } // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
671
-
672
-
571
+ }
572
+ // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
673
573
  if (propValue["@@toStringTag"] === "Symbol") {
674
574
  return true;
675
- } // Fallback for non-spec compliant Symbols which are polyfilled.
676
-
677
-
575
+ }
576
+ // Fallback for non-spec compliant Symbols which are polyfilled.
678
577
  if (typeof Symbol === "function" && propValue instanceof Symbol) {
679
578
  return true;
680
579
  }
681
-
682
580
  return false;
683
- } // Copied from React.PropTypes
684
-
685
-
581
+ }
582
+ // Copied from React.PropTypes
686
583
  function getPropType(propValue) {
687
584
  var propType = typeof propValue;
688
-
689
585
  if (Array.isArray(propValue)) {
690
586
  return "array";
691
587
  }
692
-
693
588
  if (propValue instanceof RegExp) {
694
589
  // Old webkits (at least until Android 4.0) return 'function' rather than
695
590
  // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
696
591
  // passes PropTypes.object.
697
592
  return "object";
698
593
  }
699
-
700
594
  if (isSymbol(propType, propValue)) {
701
595
  return "symbol";
702
596
  }
703
-
704
597
  return propType;
705
- } // This handles more types than `getPropType`. Only used for error messages.
598
+ }
599
+ // This handles more types than `getPropType`. Only used for error messages.
706
600
  // Copied from React.PropTypes
707
-
708
-
709
601
  function getPreciseType(propValue) {
710
602
  var propType = getPropType(propValue);
711
-
712
603
  if (propType === "object") {
713
604
  if (propValue instanceof Date) {
714
605
  return "date";
@@ -716,55 +607,43 @@ function getPreciseType(propValue) {
716
607
  return "regexp";
717
608
  }
718
609
  }
719
-
720
610
  return propType;
721
611
  }
722
-
723
612
  function createObservableTypeCheckerCreator(allowNativeType, mobxType) {
724
613
  return createChainableTypeChecker(function (props, propName, componentName, location, propFullName) {
725
614
  return untracked(function () {
726
615
  if (allowNativeType) {
727
616
  if (getPropType(props[propName]) === mobxType.toLowerCase()) return null;
728
617
  }
729
-
730
618
  var mobxChecker;
731
-
732
619
  switch (mobxType) {
733
620
  case "Array":
734
621
  mobxChecker = isObservableArray;
735
622
  break;
736
-
737
623
  case "Object":
738
624
  mobxChecker = isObservableObject;
739
625
  break;
740
-
741
626
  case "Map":
742
627
  mobxChecker = isObservableMap;
743
628
  break;
744
-
745
629
  default:
746
630
  throw new Error("Unexpected mobxType: " + mobxType);
747
631
  }
748
-
749
632
  var propValue = props[propName];
750
-
751
633
  if (!mobxChecker(propValue)) {
752
634
  var preciseType = getPreciseType(propValue);
753
635
  var nativeTypeExpectationMessage = allowNativeType ? " or javascript `" + mobxType.toLowerCase() + "`" : "";
754
636
  return new Error("Invalid prop `" + propFullName + "` of type `" + preciseType + "` supplied to" + " `" + componentName + "`, expected `mobx.Observable" + mobxType + "`" + nativeTypeExpectationMessage + ".");
755
637
  }
756
-
757
638
  return null;
758
639
  });
759
640
  });
760
641
  }
761
-
762
642
  function createObservableArrayOfTypeChecker(allowNativeType, typeChecker) {
763
643
  return createChainableTypeChecker(function (props, propName, componentName, location, propFullName) {
764
644
  for (var _len2 = arguments.length, rest = new Array(_len2 > 5 ? _len2 - 5 : 0), _key2 = 5; _key2 < _len2; _key2++) {
765
645
  rest[_key2 - 5] = arguments[_key2];
766
646
  }
767
-
768
647
  return untracked(function () {
769
648
  if (typeof typeChecker !== "function") {
770
649
  return new Error("Property `" + propFullName + "` of component `" + componentName + "` has " + "invalid PropType notation.");
@@ -772,18 +651,15 @@ function createObservableArrayOfTypeChecker(allowNativeType, typeChecker) {
772
651
  var error = createObservableTypeCheckerCreator(allowNativeType, "Array")(props, propName, componentName, location, propFullName);
773
652
  if (error instanceof Error) return error;
774
653
  var propValue = props[propName];
775
-
776
654
  for (var i = 0; i < propValue.length; i++) {
777
655
  error = typeChecker.apply(void 0, [propValue, i, componentName, location, propFullName + "[" + i + "]"].concat(rest));
778
656
  if (error instanceof Error) return error;
779
657
  }
780
-
781
658
  return null;
782
659
  }
783
660
  });
784
661
  });
785
662
  }
786
-
787
663
  var observableArray = /*#__PURE__*/createObservableTypeCheckerCreator(false, "Array");
788
664
  var observableArrayOf = /*#__PURE__*/createObservableArrayOfTypeChecker.bind(null, false);
789
665
  var observableMap = /*#__PURE__*/createObservableTypeCheckerCreator(false, "Map");
@@ -801,8 +677,12 @@ var PropTypes = {
801
677
  objectOrObservableObject: objectOrObservableObject
802
678
  };
803
679
 
804
- if (!Component) throw new Error("mobx-react requires React to be available");
805
- if (!observable) throw new Error("mobx-react requires mobx to be available");
680
+ if (!Component) {
681
+ throw new Error("mobx-react requires React to be available");
682
+ }
683
+ if (!observable) {
684
+ throw new Error("mobx-react requires mobx to be available");
685
+ }
806
686
 
807
687
  export { MobXProviderContext, PropTypes, Provider, disposeOnUnmount, inject, observer };
808
688
  //# sourceMappingURL=mobxreact.esm.development.js.map