项目要求react16升级到react18的需求,比较麻烦的是替换componentWillReceiveProps、UNSAFE_componentWillReceiveProps。以下列出几种替换场景及替换方案,方便参考替换。 主要有两种替换方案:getDerivedStateFromProps、componentDidUpdate 执行时机存在差异
1. 执行时机差异
| 方法 | 执行时机 | 能否调用 setState | 能否访问 DOM |
|---|---|---|---|
| componentWillReceiveProps | props 变化后,渲染前 | ✅ 可以 | ❌ 不能 |
| getDerivedStateFromProps | 每次渲染前 | ❌ 通过返回值更新 | ❌ 不能 |
| componentDidUpdate | 渲染完成后 | ✅ 可以 (需加条件避免无限循环) | ✅ 可以 |
简单的派生状态场景(props → state)
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.initialCount !== nextProps.initialCount) {
this.setState({
count: nextProps.initialCount
});
}
}
可直接替换为getDerivedStateFromProps,具体写法
static getDerivedStateFromProps(props, state) {
if (state.count !== props.initialCount) {
return { count: props.initialCount };
}
return null;
}
需要执行副作用(如API调用)
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.id !== nextProps.id) {
fetchData(nextProps.id);
}
}
替换为componentDidUpdate写法
componentDidUpdate(prevProps) {
if (this.props.id !== prevProps.id) {
fetchData(this.props.id);
}
}
当派生场景与副作用同时存在的长场景就需要拆分到getDerivedStateFromProps与componentDidUpdate。
简单state状态修改
如果直接修改state的优先尝试去掉state状态直接使用props里option即可
componentWillReceiveProps(nextProps) {
this.setState({
option: nextProps.option
});
}
从 componentWillReceiveProps 迁移时,关键是要理解:
- 派生状态应该使用
getDerivedStateFromProps - 副作用应该使用
componentDidUpdate - 最好重新设计组件以避免派生状态
- 考虑全面转向函数组件和Hooks