react16升级react18关于componentWillReceiveProps、UNSAFE_componentWillReceiveProps处理

120 阅读1分钟

项目要求react16升级到react18的需求,比较麻烦的是替换componentWillReceiveProps、UNSAFE_componentWillReceiveProps。以下列出几种替换场景及替换方案,方便参考替换。 主要有两种替换方案:getDerivedStateFromProps、componentDidUpdate 执行时机存在差异

1. 执行时机差异

方法执行时机能否调用 setState能否访问 DOM
componentWillReceivePropsprops 变化后,渲染前✅ 可以❌ 不能
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 迁移时,关键是要理解:

  1. 派生状态应该使用 getDerivedStateFromProps
  2. 副作用应该使用 componentDidUpdate
  3. 最好重新设计组件以避免派生状态
  4. 考虑全面转向函数组件和Hooks