The library for web and native user interfaces.
Add `ReactComponent#isMounted`
There is currently no way for components to know whether or not they are mounted. This means there's no way for callbacks to figure out if they can make certain assumptions (e.g. can `getDOMNode()` or `setState()` be safely invoked). This adds an `isMounted` protected method that lets components properly handle callback behavior when unmounted.
CommitSyncScript committed
Jun 13, 2013 at 16:32 UTC
aea8e16b4a32d179e70089edde6f1892968cf2b8
3 files changed
+24
-9
src/core/ReactComponent.js
+15
-4
@@ -188,6 +188,17 @@ var ReactComponent = {
188
*/
189
Mixin: {
190
191
+ /**
192
+ * Checks whether or not this component is mounted.
193
+ *
194
+ * @return {boolean} True if mounted, false otherwise.
195
+ * @final
196
+ * @protected
197
+ */
198
+ isMounted: function() {
199
+ return this._lifeCycleState === ComponentLifeCycle.MOUNTED;
200
+ },
201
+
202
/**
203
* Returns the DOM node rendered by this component.
204
*
@@ -201,7 +212,7 @@ var ReactComponent = {
212
'getDOMNode(): The DOM is not supported in the current environment.'
213
);
214
invariant(
204
- this._lifeCycleState === ComponentLifeCycle.MOUNTED,
215
+ this.isMounted(),
216
'getDOMNode(): A component must be mounted to have a DOM node.'
217
);
218
var rootNode = this._rootNode;
@@ -329,7 +340,7 @@ var ReactComponent = {
340
*/
341
mountComponent: function(rootID, transaction) {
342
invariant(
332
- this._lifeCycleState === ComponentLifeCycle.UNMOUNTED,
343
+ !this.isMounted(),
344
'mountComponent(%s, ...): Can only mount an unmounted component.',
345
rootID
346
);
@@ -354,7 +365,7 @@ var ReactComponent = {
365
*/
366
unmountComponent: function() {
367
invariant(
357
- this._lifeCycleState === ComponentLifeCycle.MOUNTED,
368
+ this.isMounted(),
369
'unmountComponent(): Can only unmount a mounted component.'
370
);
371
var props = this.props;
@@ -378,7 +389,7 @@ var ReactComponent = {
389
*/
390
receiveProps: function(nextProps, transaction) {
391
invariant(
381
- this._lifeCycleState === ComponentLifeCycle.MOUNTED,
392
+ this.isMounted(),
393
'receiveProps(...): Can only update a mounted component.'
394
);
395
var props = this.props;
src/core/ReactCompositeComponent.js
+2
-2
@@ -548,7 +548,7 @@ var ReactCompositeComponentMixin = {
548
replaceState: function(completeState) {
549
var compositeLifeCycleState = this._compositeLifeCycleState;
550
invariant(
551
- this._lifeCycleState === ReactComponent.LifeCycle.MOUNTED ||
551
+ this.isMounted() ||
552
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
553
'replaceState(...): Can only update a mounted (or mounting) component.'
554
);
@@ -712,7 +712,7 @@ var ReactCompositeComponentMixin = {
712
forceUpdate: function() {
713
var compositeLifeCycleState = this._compositeLifeCycleState;
714
invariant(
715
- this._lifeCycleState === ReactComponent.LifeCycle.MOUNTED,
715
+ this.isMounted(),
716
'forceUpdate(...): Can only force an update on mounted components.'
717
);
718
invariant(
src/core/__tests__/ReactNativeComponent-test.js
+7
-3
@@ -241,17 +241,21 @@ describe('ReactNativeComponent', function() {
241
242
var mixInto = require('mixInto');
243
var ReactComponent = require('ReactComponent');
244
+ var ReactMultiChild = require('ReactMultiChild');
245
var ReactNativeComponent = require('ReactNativeComponent');
246
var ReactReconcileTransaction = require('ReactReconcileTransaction');
247
247
- var NodeStub = function(initialProps) {
248
+ var StubNativeComponent = function(initialProps) {
249
ReactComponent.Mixin.construct.call(this, initialProps);
250
};
250
- mixInto(NodeStub, ReactNativeComponent.Mixin);
251
+ mixInto(StubNativeComponent, ReactComponent.Mixin);
252
+ mixInto(StubNativeComponent, ReactNativeComponent.Mixin);
253
+ mixInto(StubNativeComponent, ReactMultiChild.Mixin);
254
255
mountComponent = function(props) {
256
var transaction = new ReactReconcileTransaction();
254
- return (new NodeStub(props)).mountComponent('test', transaction);
257
+ var stubComponent = new StubNativeComponent(props);
258
+ return stubComponent.mountComponent('test', transaction);
259
};
260
});
261