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.
This commit is contained in:
CommitSyncScript
2013-06-13 17:38:20 -07:00
committed by Paul O’Shannessy
parent 0d6bb650cb
commit aea8e16b4a
3 changed files with 24 additions and 9 deletions
+15 -4
View File
@@ -188,6 +188,17 @@ var ReactComponent = {
*/
Mixin: {
/**
* Checks whether or not this component is mounted.
*
* @return {boolean} True if mounted, false otherwise.
* @final
* @protected
*/
isMounted: function() {
return this._lifeCycleState === ComponentLifeCycle.MOUNTED;
},
/**
* Returns the DOM node rendered by this component.
*
@@ -201,7 +212,7 @@ var ReactComponent = {
'getDOMNode(): The DOM is not supported in the current environment.'
);
invariant(
this._lifeCycleState === ComponentLifeCycle.MOUNTED,
this.isMounted(),
'getDOMNode(): A component must be mounted to have a DOM node.'
);
var rootNode = this._rootNode;
@@ -329,7 +340,7 @@ var ReactComponent = {
*/
mountComponent: function(rootID, transaction) {
invariant(
this._lifeCycleState === ComponentLifeCycle.UNMOUNTED,
!this.isMounted(),
'mountComponent(%s, ...): Can only mount an unmounted component.',
rootID
);
@@ -354,7 +365,7 @@ var ReactComponent = {
*/
unmountComponent: function() {
invariant(
this._lifeCycleState === ComponentLifeCycle.MOUNTED,
this.isMounted(),
'unmountComponent(): Can only unmount a mounted component.'
);
var props = this.props;
@@ -378,7 +389,7 @@ var ReactComponent = {
*/
receiveProps: function(nextProps, transaction) {
invariant(
this._lifeCycleState === ComponentLifeCycle.MOUNTED,
this.isMounted(),
'receiveProps(...): Can only update a mounted component.'
);
var props = this.props;
+2 -2
View File
@@ -548,7 +548,7 @@ var ReactCompositeComponentMixin = {
replaceState: function(completeState) {
var compositeLifeCycleState = this._compositeLifeCycleState;
invariant(
this._lifeCycleState === ReactComponent.LifeCycle.MOUNTED ||
this.isMounted() ||
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
'replaceState(...): Can only update a mounted (or mounting) component.'
);
@@ -712,7 +712,7 @@ var ReactCompositeComponentMixin = {
forceUpdate: function() {
var compositeLifeCycleState = this._compositeLifeCycleState;
invariant(
this._lifeCycleState === ReactComponent.LifeCycle.MOUNTED,
this.isMounted(),
'forceUpdate(...): Can only force an update on mounted components.'
);
invariant(
@@ -241,17 +241,21 @@ describe('ReactNativeComponent', function() {
var mixInto = require('mixInto');
var ReactComponent = require('ReactComponent');
var ReactMultiChild = require('ReactMultiChild');
var ReactNativeComponent = require('ReactNativeComponent');
var ReactReconcileTransaction = require('ReactReconcileTransaction');
var NodeStub = function(initialProps) {
var StubNativeComponent = function(initialProps) {
ReactComponent.Mixin.construct.call(this, initialProps);
};
mixInto(NodeStub, ReactNativeComponent.Mixin);
mixInto(StubNativeComponent, ReactComponent.Mixin);
mixInto(StubNativeComponent, ReactNativeComponent.Mixin);
mixInto(StubNativeComponent, ReactMultiChild.Mixin);
mountComponent = function(props) {
var transaction = new ReactReconcileTransaction();
return (new NodeStub(props)).mountComponent('test', transaction);
var stubComponent = new StubNativeComponent(props);
return stubComponent.mountComponent('test', transaction);
};
});