你应该做的是在你的组件上设置状态,而不是在你的 React 组件上将状态作为任意属性。
所以不要这样做:
var MyComponent = React.createClass({
myArray: [1, 2, 3],
componentWillMount() {
this.myArray.push(this.myArray.length + 1);
},
render() {
return (
<span>{this.myArray.length}</span>
);
}
});
你应该这样做:
var MyComponent = React.createClass({
getInitialState() {
return {
myArray: [1, 2, 3]
};
},
componentWillMount() {
this.setState(state => {
state.myArray.push(state.myArray.length + 1);
return state;
});
},
render() {
return (
<span>{this.myArray.length}</span>
);
}
});
原因是所有组件的状态和数据都应该驻留在由 React 控制和处理的 this.state 和 this.props 中。
为此使用 props 和 state 的好处是,React 会知道它们何时发生变化,并据此判断何时需要重新渲染组件。如果您将状态存储为任意属性或全局变量,React 将不知道它们何时更改,并且无法为您重新渲染。
您所看到的行为的原因是组件的每个实例都使用您提供给React.createClass() 的对象作为其原型。所以组件的所有实例都有一个myArray 属性,但它在原型链上,因此被所有实例共享。
如果你真的想要这样的东西并且你想避免this.state,你应该使用类似componentWillMount的东西,并在该方法中,将属性分配给this。这将确保此类数据仅在该特定实例上,而不是在原型链上。
编辑
为了进一步澄清,最好知道传递给React.createClass() 的对象不是原型上的实际对象。 React 所做的是它遍历该对象上的所有属性,并将它们复制到 React 元素对象的原型上。这个例子可以说明这一点:
var obj = {
myArray: [1, 2, 3],
title: 'My title',
componentWillMount() {
this.myArray.push(this.myArray.length + 1);
},
render() {
return (
<span>{this.myArray.length}</span>
);
}
}
var MyComponent = React.createClass(obj);
// This doesn't change the component, since 'obj' isn't used anymore
// by React, it has already copied all properties.
obj.title = 'New title';
// This however affects the component, because the reference to the array
// was copied to the component prototype, and any changes to what the
// reference points to will affect everyone who has access to it.
obj.myArray.push(666);