Props
无论是类组件还是函数组件它们绝对不能修改自己的 props
state
- 不要直接更新状态,应当使用 setState({key: value})
- 状态更新可能是异步的
- 一个生命周期内 React 可以将多个 setState()合并为一个调用来提升性能。
- 对于依靠 state 的值来计算下一个状态时应该使用以下形式
jsx
// 该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment,
}));
- state 的更新会被合并,可以分别调用 setState()来单独的更新它们
生命周期
组件的挂载
constructor(props)
- 通过 this.state 赋值对象来初始化内部 state
- 为事件处理函数绑定实例
- 注意:避免将 props 的值赋值直接赋值给 state,如此做毫无必要,同时还产生了 bug(当父组件传递给子组件的 props 改变的时候并不会影响到子组件的 state)
static getDerivedStateFromProps(props, state)
- getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始化挂载及后续更新时都会被调用
- 它应该返回一个对象来更新 state,如果返回 null 则不更新任何内容,但是派生 state 会导致代码冗余,并且使得组件难以维护
- 应用:让组件在 props 变化时更新 state
- 注意:
- 不管 props 有没有变化,只要父组件重新渲染,getDerivedStateFromProps 就会被调用,所以直接将 props 复制到 state 是不安全的
- 如果需要执行副作用以响应 props 的更改,请改用 componentDidUpdate
- 如果指向在 props 更改时重新计算某些数据,请使用 memoization
render()
- render()方法是 class 组建中唯一必须实现的方法
- render()函数为纯函数
componentDidMount()
- componentDidMount()会在组件挂载后(插入 DOM 树中)立即调用
- 依赖 DOM 节点的初始化应该放在 componentDidMount()函数中
- 通过网络请求获取数据的操作最好放在 componentDidMount()函数中
- 适合添加订阅,如果在此函数中添加了订阅一定要在 componentDidUnmount()里取消订阅
- 可以在 componentDidMount()里直接调用 setState(),它会触发额外的渲染,在此渲染会发生在浏览器更新之前(会导致性能问题,慎用!)
组件的更新
static getDerivedStateFromProps(props, state)
shouldComponentUpdate(nextProps, nextState)
- 根据 shouldComponentUpdate()的返回值(true/false)判断 React 组件是否渲染,默认值为 true
- 当 props 或 state 发生变化时,shouldComponentUpdate()会在渲染执行前被调用,首次渲染或者使用 forceUpdate()时不会调用该方法
- 此方法仅作为性能优化的方式存在
- 再后续的版本中可能会将 shouldComponentUpdate 视为提示而不是严格的指令,并且当返回 false 时任然可能导致组建的重新渲染
render()
getSnapshotBeforeUpdate(prevProps, prevState)
- getSnapshotBeforeUpdate()在最近一次渲染输出(提交到 DOM 节点)之前调用
- getSnapshotBeforeUpdate()是得组件在发生更改之前从 DOM 中捕获一些信息
- getSnapshotBeforeUpdate()的返回值将作为参数传递给 componentDidUpdate()
- 应用:不常用,处理滚动位置等
componentDidUpdate(prevProps, prevState, snapshot)
- componentDidUpdate()会在更新后立即被调用,首次渲染不会执行此方法
- 最更新前后如果对 props 进行了对比,也可以在此方法中进行网络请求
- 也可以在此方法里直接调用 setState(),但必须将它包裹在一个调价语句中,否则会导致死循环
- 如果组件实现了 getSnapshotBeforeUpdate()生命周期,则它的返回值将作为 componentDidUpdate()的第三个参数进行传递,否则此参数为 undefined
- 注意:如果 shouldComponentUpdate()返回值为 false,则不会调用 componentDidUpdate()
组件的卸载
componentWillUnmount()
- 会在组件卸载或者销毁之前直接调用
- 在此方法中执行必要的清理操作,例如:清除 timer,取消网络请求或者消除在 componentDidMount()中创建的订阅等
错误的处理
static getDerivedStateFromError(error)
- 此生命周期会在后代组件抛出错误后被调用,他讲抛出的错误作为参数,并返回一个值以更新 state
- 注意:getDerivedStateFromError()会在渲染阶段调用,因此不允许出现副作用,如遇此类情况请改用 componentDidCatch()
componentDidCatch(error, info)
- 此生命周期在后代组件抛出错误后被调用,它接受两个参数:
- error: 抛出的错误
- info: 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息
- componentDidCatch()会在提交阶段被调用,因此允许执行副作用
- 注意:在发生错误时可以通过 setState 使用 componentDidCatch()渲染降级 UI,但在未来的版本中将不推荐这样的做法。可以使用 getDerivedStateFromError()来处理降级渲染
其他 API
setState()
setState(updater[, callback])
- setState()将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件
- 为了更好的感知性能,React 会延迟调用 setState(),然后通过一次传递更新多个组件。React 不会保证 state 的变更会立即生效。
- setState()并不总是立即更新组件,所以使用 componentDidUpdate()或者 setState()的回调函数获取更新后的 state 更安全
setState((state, props) => stateChange)
component.forceUpdate(callback)
- 默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render()方法依赖于其他数据,则可以调用 forceUpdate 强制让组件重新渲染
- 调用 forceUpdate 将使组件调用 render 方法,此操作会跳过该组件的 shouldComponentUpdate 方法
- 避免使用 forceUpdate,尽量在 render 中使用 this.props 和 this.state
class 属性
defaultProps
- 为 class 组件添加默认的 props
displayName
- 多用于调试消息