react v16.3 版本的发布,生命周期函数的变更去掉了如下三个html
同时为了弥补失去上面三个周期的不足又加了两个react
过分方案是在以前项目中使用去掉的函数添加前缀 UNSAFE_, 官网提示能够继续使用至 React 17。但在项目中依然会有一些waring ,建议修改。如下是项目中一些替换策略,涉及也是比较全面,且有我深刻浅出一一阐述。数组
componentWillMount 函数中的场景有一下种:bash
在此方法中引入任何反作用或订阅。如遇此种状况,请改用 componentDidMount()
componentWillReceiveProps 函数在初始的props不会渲染。会在组件接受到新的 props 时调用。通常用于父组件更新状态时子组件的从新渲染。替换的场景以下:dom
替换策略:异步
若是您须要 执行反作用 (side effect)(例如,数据获取或动画)以响应 属性 (props) 的更改,使用 componentDidUpdate 生命周期方法ide
使用 componentWillReceiveProps, 在属性 (props) 改变 时从新计算一些数据,请使用 memoization 辅助工具-官网有例子函数
使用 componentWillReceiveProps , 在属性 (props) 改变时 “重置” 一些 state (状态),考虑使用一个 彻底控制组件 或 一个 带 key 的彻底不受控 组件工具
可使用 static getDerivedStateFromProps + componentDidUpdate vs getSnapshotBeforeUpdate + componentDidUpdate性能
以上3种状况是官网推荐, 也是比较简单的方式。static getDerivedStateFromProps 函数是官网也不推荐使用的函数,因此命名就比较长, 项目中对对此函数的替换在不拆分组件, 没有使用hook的状况下使用第3种策略进行的改写。
static getDerivedStateFromProps(props, state)
在调用 render 方法以前被调用,包括初始装载(mount)和后续更新时。 它应该返回一个更新 state (状态) 的对象,或者返回 null 以不更新任何 state (状态)。
getSnapshotBeforeUpdate(prevProps, prevState)
在最近一次的渲染输出被提交以前调用, 它返回的值将做为第三个 snapshot 参数传递给 componentDidUpdate() 。 不然这个参数将是 undefined componentDidUpdate(prevProps, prevState, snapshot)
此方法能够调用 setState()来操做 DOM 。但请注意,必须包含在条件语句中 像上面的例子同样,不然你会致使无限循环。 这也会致使额外的从新渲染, 虽然对用户不可见,可是会影响组件的性能。
例子1更改前
UNSAFE_componentWillReceiveProps(nextProps) {
const { models = [], itemId, shopId } = nextProps.sellerData;
const { itemId: currentItemId } = this.props.sellerData;
if (itemId !== currentItemId && models.length && models.length > 0) {
this.setState(
{
matchShop: {}, // 初始化state
},
// callback 中调用 this.props 中父组件的方法
() => {
this.init(models);
this.props.onGetMatchingTable({
modelid: models[0].model_id,
itemId,
shopId
});
}
);
}
}
复制代码
例子1更改后
// getDerivedStateFromProps 接收最新的 Props 值 nextProps、上一个 state 值 prevState 两个参数,返回返回一个对象来更新 state,或者返回 null 表示不须要更新 state。
static getDerivedStateFromProps(nextProps, prevState) {
const { models = [], itemId, shopId } = nextProps.sellerData;
const { itemId: currentItemId } =
(prevState && prevState.preSellerData) || '';
if (
currentItemId !== '' &&
itemId !== currentItemId &&
models.length &&
models.length > 0
) {
return {
matchShop: {},
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
const { itemId: currentItemId } = prevProps.sellerData;
const { models = [], itemId, shopId } = this.props.sellerData;
if (itemId !== currentItemId && models.length && models.length > 0) {
// console.log('prevState---this.props', this.props, prevState, prevProps);
this.init(models);
this.props.onGetMatchingTable({
modelid: models[0].model_id,
itemId,
shopId
});
}
}
复制代码
例子2 state状态中iptUrl 是在子组件中,而且都多处能够变动,父组件传值props 用户能够输入url,这种状况下使用 getDerivedStateFromProps静态方法就会触发页面更改进入死循环。使用getSnapshotBeforeUpdate + componentDidUpdate进行替换修改。
// 更改前注释状态
// UNSAFE_componentWillReceiveProps(nextProps) {
// if (nextProps.url !== this.state.iptUrl) {
// this.setState({
// iptUrl: nextProps.url,
// errMsg: ''
// });
// }
// }
// 更改后
getSnapshotBeforeUpdate(prevProps, prevState) {
if (prevProps.url !== this.props.url) {
return this.props.url;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
this.setState({ iptUrl: this.props.url, errMsg: '' });
}
}
复制代码
在React 16.8 版本中可使用 Effect Hook, useEffect Hook 看作 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。在hook 中没有生命周期的概念,更改数据的操做均可以称为反作用。Effect Hook 可让你在函数组件中执行反作用操做。