Use hack to support isMounted without stateful module
This hack allow us to get rid of the stateful module ReactLifeCycle since we can infer the value of isMounted even without it. This gets rid of the try/catch which is deopting all mountComponent calls. As a next step we could deprecate isMounted completely and avoid stateful APIs. Since it can be easily simulated if you truly need it.
Sebastian Markbage committed
Jun 18, 2015 at 14:10 UTC
dddebd1344d08b901a92f76891494a81f8045e6c
4 files changed
+12
-85
src/renderers/shared/reconciler/ReactCompositeComponent.js
+8
-17
@@ -16,7 +16,6 @@ var ReactCurrentOwner = require('ReactCurrentOwner');
16
var ReactElement = require('ReactElement');
17
var ReactElementValidator = require('ReactElementValidator');
18
var ReactInstanceMap = require('ReactInstanceMap');
19
-var ReactLifeCycle = require('ReactLifeCycle');
19
var ReactNativeComponent = require('ReactNativeComponent');
20
var ReactPerf = require('ReactPerf');
21
var ReactPropTypeLocations = require('ReactPropTypeLocations');
@@ -218,25 +217,17 @@ var ReactCompositeComponentMixin = {
217
this._pendingReplaceState = false;
218
this._pendingForceUpdate = false;
219
221
- var renderedElement;
222
-
223
- var previouslyMounting = ReactLifeCycle.currentlyMountingInstance;
224
- ReactLifeCycle.currentlyMountingInstance = this;
225
- try {
226
- if (inst.componentWillMount) {
227
- inst.componentWillMount();
228
- // When mounting, calls to `setState` by `componentWillMount` will set
229
- // `this._pendingStateQueue` without triggering a re-render.
230
- if (this._pendingStateQueue) {
231
- inst.state = this._processPendingState(inst.props, inst.context);
232
- }
220
+ if (inst.componentWillMount) {
221
+ inst.componentWillMount();
222
+ // When mounting, calls to `setState` by `componentWillMount` will set
223
+ // `this._pendingStateQueue` without triggering a re-render.
224
+ if (this._pendingStateQueue) {
225
+ inst.state = this._processPendingState(inst.props, inst.context);
226
}
234
-
235
- renderedElement = this._renderValidatedComponent();
236
- } finally {
237
- ReactLifeCycle.currentlyMountingInstance = previouslyMounting;
227
}
228
229
+ var renderedElement = this._renderValidatedComponent();
230
+
231
this._renderedComponent = this._instantiateReactComponent(
232
renderedElement,
233
this._currentElement.type // The wrapping type
src/renderers/shared/reconciler/ReactLifeCycle.js
deleted
-29
@@ -1,29 +0,0 @@
1
-/**
2
- * Copyright 2015, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- *
9
- * @providesModule ReactLifeCycle
10
- */
11
-
12
-'use strict';
13
-
14
-/**
15
- * This module manages the bookkeeping when a component is in the process
16
- * of being mounted or being unmounted. This is used as a way to enforce
17
- * invariants (or warnings) when it is not recommended to call
18
- * setState/forceUpdate.
19
- *
20
- * currentlyMountingInstance: During the construction phase, it is not possible
21
- * to trigger an update since the instance is not fully mounted yet. However, we
22
- * currently allow this as a convenience for mutating the initial state.
23
- */
24
-
25
-var ReactLifeCycle = {
26
- currentlyMountingInstance: null,
27
-};
28
-
29
-module.exports = ReactLifeCycle;
src/renderers/shared/reconciler/ReactUpdateQueue.js
+4
-2
@@ -11,7 +11,6 @@
11
12
'use strict';
13
14
-var ReactLifeCycle = require('ReactLifeCycle');
14
var ReactCurrentOwner = require('ReactCurrentOwner');
15
var ReactElement = require('ReactElement');
16
var ReactInstanceMap = require('ReactInstanceMap');
@@ -89,7 +88,10 @@ var ReactUpdateQueue = {
88
}
89
var internalInstance = ReactInstanceMap.get(publicInstance);
90
if (internalInstance) {
92
- return internalInstance !== ReactLifeCycle.currentlyMountingInstance;
91
+ // During componentWillMount and render this will still be null but after
92
+ // that will always render to something. At least for now. So we can use
93
+ // this hack.
94
+ return !!internalInstance._renderedComponent;
95
} else {
96
return false;
97
}
src/renderers/shared/reconciler/__tests__/ReactComponentLifeCycle-test.js
-37
@@ -14,7 +14,6 @@
14
var keyMirror = require('keyMirror');
15
16
var React;
17
-var ReactLifeCycle;
17
var ReactInstanceMap;
18
var ReactTestUtils;
19
@@ -80,28 +79,6 @@ var ComponentLifeCycle = keyMirror({
79
UNMOUNTED: null,
80
});
81
83
-/**
84
- * Composite components can also be in one of these life cycles.
85
- */
86
-var CompositeComponentLifeCycle = keyMirror({
87
- /**
88
- * Mounted components have a DOM node representation and are capable of
89
- * receiving new props.
90
- */
91
- MOUNTING: null,
92
-});
93
-
94
-function getCompositeLifeCycle(instance) {
95
- var internalInstance = ReactInstanceMap.get(instance);
96
- if (!internalInstance) {
97
- return null;
98
- }
99
- if (ReactLifeCycle.currentlyMountingInstance === internalInstance) {
100
- return CompositeComponentLifeCycle.MOUNTING;
101
- }
102
- return null;
103
-}
104
-
82
function getLifeCycleState(instance) {
83
var internalInstance = ReactInstanceMap.get(instance);
84
// Once a component gets mounted, it has an internal instance, once it
@@ -123,7 +100,6 @@ describe('ReactComponentLifeCycle', function() {
100
require('mock-modules').dumpCache();
101
React = require('React');
102
ReactTestUtils = require('ReactTestUtils');
126
- ReactLifeCycle = require('ReactLifeCycle');
103
ReactInstanceMap = require('ReactInstanceMap');
104
});
105
@@ -335,8 +311,6 @@ describe('ReactComponentLifeCycle', function() {
311
this._testJournal.returnedFromGetInitialState = clone(initState);
312
this._testJournal.lifeCycleAtStartOfGetInitialState =
313
getLifeCycleState(this);
338
- this._testJournal.compositeLifeCycleAtStartOfGetInitialState =
339
- getCompositeLifeCycle(this);
314
return initState;
315
},
316
@@ -344,8 +318,6 @@ describe('ReactComponentLifeCycle', function() {
318
this._testJournal.stateAtStartOfWillMount = clone(this.state);
319
this._testJournal.lifeCycleAtStartOfWillMount =
320
getLifeCycleState(this);
347
- this._testJournal.compositeLifeCycleAtStartOfWillMount =
348
- getCompositeLifeCycle(this);
321
this.state.hasWillMountCompleted = true;
322
},
323
@@ -361,8 +333,6 @@ describe('ReactComponentLifeCycle', function() {
333
if (isInitialRender) {
334
this._testJournal.stateInInitialRender = clone(this.state);
335
this._testJournal.lifeCycleInInitialRender = getLifeCycleState(this);
364
- this._testJournal.compositeLifeCycleInInitialRender =
365
- getCompositeLifeCycle(this);
336
} else {
337
this._testJournal.stateInLaterRender = clone(this.state);
338
this._testJournal.lifeCycleInLaterRender = getLifeCycleState(this);
@@ -396,8 +366,6 @@ describe('ReactComponentLifeCycle', function() {
366
);
367
expect(instance._testJournal.lifeCycleAtStartOfGetInitialState)
368
.toBe(ComponentLifeCycle.UNMOUNTED);
399
- expect(instance._testJournal.compositeLifeCycleAtStartOfGetInitialState)
400
- .toBe(null);
369
370
// componentWillMount
371
expect(instance._testJournal.stateAtStartOfWillMount).toEqual(
@@ -405,8 +373,6 @@ describe('ReactComponentLifeCycle', function() {
373
);
374
expect(instance._testJournal.lifeCycleAtStartOfWillMount)
375
.toBe(ComponentLifeCycle.MOUNTED);
408
- expect(instance._testJournal.compositeLifeCycleAtStartOfWillMount)
409
- .toBe(CompositeComponentLifeCycle.MOUNTING);
376
377
// componentDidMount
378
expect(instance._testJournal.stateAtStartOfDidMount)
@@ -421,9 +387,6 @@ describe('ReactComponentLifeCycle', function() {
387
expect(instance._testJournal.lifeCycleInInitialRender).toBe(
388
ComponentLifeCycle.MOUNTED
389
);
424
- expect(instance._testJournal.compositeLifeCycleInInitialRender).toBe(
425
- CompositeComponentLifeCycle.MOUNTING
426
- );
390
391
expect(getLifeCycleState(instance)).toBe(ComponentLifeCycle.MOUNTED);
392