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