一、setState(updater[, callback])

setState() 方法将组件中 state 的变化进入队列中,然后会通知 React 需要其组建和子组件需要给予更新后的 state 进行 re-render。

这是响应事件处理以及服务端数据请求之后进行用于UI界面更新的主要方法。

应当把 setState 当做一种请求而不是立即执行起作用的命令。为了优化性能,React 可能不会立即对 setState 起作用,而是可能会延迟,然后一次执行中,更新几个组件。React 不能保证响应 state 的更改。

setState 并不总是立即更新组件,可能会批量或者单个延缓到之后再进行更新。因此,在调用 setState 方法之后立即获取 this.state 可能会存在问题,相反,在 componentDidUpdate 或者是 setState 回调(setState(updater, callback))中获取 this.state 都能保证拿到更新后的 state。

除非在 shouldComponentUpdate 中 return false,否则每次执行的 setState 始终都会引起 re-render。如果正在使用可变对象,并且无法在 shouldComponentUpdate 中判断是否应当更新,那么应当进行有条件的 setState 操作,也就是仅当前 state 与之前 state 不同时调用 setState 将避免不必要的 re-render。

setState 的第一个参数是一个带有签名的 updater 方法:

(state, props) => stateChange

state 是对应用更改时组件 state 的引用,state 不应该直接进行更改,应当通过基于 state 和 props 来构建新的对象来表示更改,比如,如果希望通过 props.step 更改 state 时:

this.setState((state, props) => {
    return {counter: state.counter + props.step}
});

上面的 setState 在执行的时候,参数的 state 和 props 都保证是最新的,其实就是 updater 的输出和 state 的浅合并。

setState 的第二个参数是一个可选的回调方法,一旦完成 setState 并重新渲染组件,这个回调方法会被执行。不过一般来说是建议在 componentDidUpdate 中替代在 setState 中回调的方式。

当然,setState 用法最多的时候,往往第一个参数传递一个对象而不是函数:

setState(stateChange[, callback])

下面的示例中,会将 stateChange 浅层合并到新的 state:

this.setState({quantity: 2})

这种新式的 setState 是异步的,并且在同一周期内的多个调用可以一起批量处理。例如,如果尝试在同一个周期中多次增加项目数量,则和下面的示例是等效的:

this.setState((state) => {
  return {quantity: state.quantity + 1};
});

关于 detail 的更多文档:

二、forceUpdate()

在默认情况下,组件的状态或者是 props 发生更改的时候,组件将触发 re-render。如果 render 方法依赖于其他的一些数据,可以通过调用 forceUpdate() 告诉 React 该组件需要进行 re-render。

如果调用 forceUpdate 将导致在组件上直接调用 render,并且会直接跳过 shouldComponentUpdate。不过这会触发子组件的正常生命周期方法,包括每个子组件的 shouldComponentUpdate 方法,如果 markup 发生了变化,React 仍然只会更新DOM。

通常应该尽量避免使用 forceUpdate,并且应当只在 render 方法中 读取 this.propsthis.state。(不过后面这一点是不显示的,因为事件处理或者其他一些复杂逻辑操作,总是会用到的)

三、类属性:defaultProps

defaultProps 可以定义为组件类本身的属性,用来设置类的默认 props,只对 undefined 的 props,而不是用于null 值的 props。比如:

class CustomButton extends React.Component {
  // ...
}

CustomButton.defaultProps = {
  color: 'blue'
};

如果父组件使用该组件的时候,没有显示传递 props,则会直接将上面的 this.props.color 置为 blue:

render() {
    return <CustomButton /> ; // props.color will be set to blue
  }

如果父组件使用子组件的时候,显示的传递了一个 null 给 props.color,则这个值就是null,而不是 blue:

render() {
    return <CustomButton color={null} /> ; // props.color will remain null
  }

四、类属性:displayName

displayName 字符串用于 debug 的信息,通常,不需要显示的去设置,因为能够从定义组件的函数或者是类的名称推断出来。

如果为了 debug 的目的需要显示不同的名称或者创建更高阶的组件时,可能需要显示设置它,有关更多详细的信息可以参照通过 Display Name 来轻松 debug

五、实例属性:props

this.props 包含有该组件的调用者定义的 props,更多关于 props 的使用可以看 组件和 props 的文档。

比较特比的是,this.props.children 是一个特殊的 prop,通常是由JSX表达式中的子标签而不是标签本身定义。

六、实例属性:state

状态包含特定于此组件的数据,该数据可能会随着时间而进行变化。而状态是用户定义的,它应该是一个普通的 javascript 对象。

如果某些值没有用于 render 或数据流(比如:计时器的 id),那么没必要把这种值挂到 state 上,而是应该使用实例属性来代替,比如 this.timer

可以在 state 和生命周期 文档中查看更多关于 state 的内容。

绝对不要去直接改变 state,因为如果在直接改变 state 之后再调用 setState 可能会直接覆盖掉之前的突变行为,因此在使用过程中,应当将 this.state 看作是不可变的。