React 中的 state(状态)是简单的 JavaScript 对象,用于管理组件内的状态。请牢记:只有用在渲染(render)过程中的数据才保存在状态里。
什么是状态(State) Link to heading
React 组件用状态来保存相关数据,它本身就是一个简单的对象。状态和普通对象的区别在于,React 会监视状态的属性,并在它更新时触发组件重新渲染。
状态更新会触发重新渲染,因此可以只用它来保存渲染所需的数据。换句话说,虽与组件相关但不用于 render 方法的变量就无需保存在状态里了,使用实例变量即可。
同时,你还可以认为状态就是组件的私有数据,只有在组件内才能读取或更新状态。我们不能在它的父组件或子组件里访问状态。
与属性(Props)的区别 Link to heading
和 props 类似,状态就是一个用于触发组件重新渲染的对象。区别在于 props 来自父组件,状态是组件的内部数据。
我们无法在组件内更新 props。因为它是来自外部的数据,组件不能对其进行操作。状态处于组件内部,组件对它有完全操作的能力。
如下图:

初始化状态 Link to heading
我们有多种方式来初始化组件的状态:
- 使用
getInitialState方法 - 在
constructor方法内初始化 - 以类属性的方式初始化
使用 getInitialState 方法
Link to heading
使用 React.createClass 来定义组件时,可以使用 getInitialState 方法:
import React from 'react';
const ExampleComponent = React.createClass({
getInitialState () {
return {
someKey: 'someValue'
};
},
render() {
return (
<div>{this.state.someKey}</div>
);
}
});
export default ExampleComponent;
在 constructor 方法内初始化
Link to heading
当你使用 ES6 的 Class 关键字定义组件时,可以在 constructor 方法里初始化状态:
import React from 'react';
class ExampleComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
someKey: 'someValue'
};
}
render() {
return (
<div>{this.state.someKey}</div>
);
}
}
export default ExampleComponent;
请不要忘记调用 super() 方法,否则在 constructor 内将无法使用 this。不要漏掉了 super 方法里的 props 参数。
以类属性的方式初始化 Link to heading
同样在使用 ES6 的 Class 关键字时,我们还可以用类属性的方式初始化状态。这种写法可以节省几行代码:
import React from 'react';
class ExampleComponent extends React.Component {
state = { someKey: 'someValue' }
render() {
return (
<div>{this.state.someKey}</div>
);
}
}
export default ExampleComponent;
更新状态 Link to heading
更新状态时,需要留意如下规则:
- 不要直接修改状态的属性值
- 警告:
setState是一个异步方法 - 状态更新会合并操作
不要直接修改状态的属性值 Link to heading
第一条规则就是「不要向任何人提起状态更新」,恩不对,好像进错片场了。第一条规则是:不要直接修改状态的属性值。
// 不要这样做
this.state.someValueInState = 'NEW VALUE';
我们只能在初始化状态时直接写入状态,比如在 constructor 里进行定义。
除了初始化之外,我们只能使用 this.setState 方法来更新状态:
this.setState({someValueInState: 'NEW VALUE'});
警告:setState 是一个异步方法
Link to heading
请留意 setState 的两个关键点:第一,在计算下一个状态时不能依赖 this.state 和 this.props,它们可能会被异步更新:
// 不要这样做
this.setState({
counter: this.state.counter + this.props.increment,
});
在这种情况下,用 function 作为 setState 的第一个参数即可:
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
第二,由于 setState 是异步执行的,因此我们不能依赖 this.setState 之后马上取得的 this.state 值。
如果你要在状态真正完成更新时执行代码,请使用 this.setState 的第二个参数,回调函数:
this.setState({
someKey: 'someValue',
}, () => {
// 只有在状态完成更新后,才会执行这里的代码
}
);
state 更新会合并操作
Link to heading
当我们调用 setState 方法时,React 将把参数传递的对象合并到当前的状态中。我们不必担心会出现属性覆盖的情况。
假设我们在 constructor 中定义了一个状态:
constructor(props) {
super(props);
this.state = {
someKey: 'someValue',
someOtherKey: 'someOtherValue'
};
}
之后,我们可以用 setState 分别更新这两个属性:
this.setState({
someKey: 'someNewValue'
});
在上面的代码里,this.state.someOtherKey 就不会被覆盖。