react 16.3+ 新生命周期
react 16.3版本出现了两个新的生命周期函数,并将逐渐废弃componentWillMount()、componentWillReceiveProps()、componentWillUpdate()
1、static getDerivedStateFromProps(props, state)
注意:
最常见的误解就是 getDerivedStateFromProps
和 componentWillReceiveProps
只会在 props “改变”时才会调用。实际上只要父级重新渲染时,这两个生命周期函数就会重新调用,不管 props 有没有“变化”。
getDerivedStateFromProps
的存在只有一个目的:让组件在 props 变化时更新 state
名词“受控”和“非受控”通常用来指代表单的 inputs,但是也可以用来描述数据频繁更新的组件。用 props 传入数据的话,组件可以被认为是受控(因为组件被父级传入的 props 控制)。数据只保存在组件内部的 state 的话,是非受控组件(因为外部没办法直接控制 state)
设计组件时,重要的是确定组件是受控组件还是非受控组件。在实际应用中,组件一般都会有受控组件和非受控组件。
任何数据,都要保证只有一个数据来源(明确的数据来源),而且避免直接复制它
constructor(props) { super(props); // 不要这样做 this.state = { color: props.color }; }
这种情况可能会造成数据来源不只一个(如果使用也setState更新color的话),并且可能会造成父组件props.color改变子组件state里的color并没有改变。解决方法是:(1)完全做成受控组件,不用state,由props进行控制(2)只有在你刻意忽略props更新的时候使用,应将 props.color 重命名为 props.initialColor
或 props.defaultColor
非受控组件,后续更新完全由setState控制
不要直接复制(mirror) props 的值到 state 中,而是去实现一个受控的组件,然后在父组件里合并两个值。比如,不要在子组件里被动的接受 props.value
并跟踪一个临时的 state.value
,而要在父组件里管理 state.draftValue
和 state.committedValue
,直接控制子组件里的值。这样数据才更加明确可预测。
对于不受控的组件,当你想在 prop 变化(通常是 ID )时重置 state 的话,可以选择一下几种方式:
- 建议: 重置内部所有的初始 state,使用
key
属性(当key
变化时, React 会创建一个新的而不是更新一个既有的组件) - 选项一:仅更改某些字段,观察特殊属性的变化(比如
props.userID
)。 - 选项二:使用 ref 调用实例方法
派生状态会导致代码冗余,并使组件难以维护。 确保你已熟悉这些简单的替代方案:
-
如果你需要执行副作用(例如,数据提取或动画)以响应 props 中的更改,请改用
componentDidUpdate
。 -
如果只想在 prop 更改时重新计算某些数据,请使用 memoization helper 代替。
-
如果你想在 prop 更改时“重置”某些 state,请考虑使组件完全受控或使用
key
使组件完全不受控 代替。
2、getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate()
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等