博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React Hook watch功能
阅读量:4090 次
发布时间:2019-05-25

本文共 4322 字,大约阅读时间需要 14 分钟。

react 生命周期函数变更

react v16.3 版本的发布,生命周期函数的变动去掉了以下三个

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

同时为了弥补失去上面三个周期的不足又加了两个

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

过度方案是在之前项目中使用去掉的函数添加前缀 UNSAFE_, 官网提示可以继续使用至 React 17。但在项目中依然会有一些waring ,建议修改。以下是项目中一些替换策略,涉及也是比较全面,且有我深入浅出一一阐述。

UNSAFE_componentWillMount 的替换

componentWillMount 函数中的场景有一下种:

  • class component中state 初始化数据状态的设置
    • 官网建议使用 constructor() 来初始化 state。
  • 异步拉取数据
    • 可以放在componentDidMount 函数中 引用官网原句在此方法中引入任何副作用或订阅。如遇此种情况,请改用 componentDidMount()
  • 定时器
    • 可以在 componentDidMount 函数中
    • 另一种方式是把定时器的抽离新的子组件(涉及业务逻辑的都可以放在子组件中)

UNSAFE_componentWillReceiveProps 的替换

componentWillReceiveProps 函数在初始的props不会渲染。会在组件接受到新的 props 时调用。一般用于父组件更新状态时子组件的重新渲染。替换的场景如下:

  • 对比 this.prop和nextProps
  • 根据 nextProps更新state的操作 (见例子2)
    • 不影响dom界面的显示
    • 影响dom界面的显示
  • 根据 nextProps更新state,并且有调用this.props的操作(见例子1)

替换策略:

  • 如果您需要 执行副作用 (side effect)(例如,数据获取或动画)以响应 属性 (props) 的更改,使用 componentDidUpdate 生命周期方法

  • 使用 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: '' });    }  }复制代码

使用 Effect Hook

在React 16.8 版本中可以使用 Effect Hook, useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。在hook 中没有生命周期的概念,更改数据的操作都可以称为副作用。Effect Hook 可以让你在函数组件中执行副作用操作。

参考

作者:yanziNote
链接:https://juejin.im/post/5df1e109f265da33bc57d753
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的文章
[总结]高效的jQuery代码编写技巧
查看>>
《JavaScript高级程序设计》笔记:客户端检测(九)
查看>>
如何处理大数据量抽数长期无响应
查看>>
Git学习
查看>>
http基础扩展
查看>>
Java中OutOfMemoryError(内存溢出)的三种情况及解决办法
查看>>
Lua Table 操作
查看>>
[编写高质量代码:改善java程序的151个建议]建议86,87 default值,valueOf
查看>>
Java枚举
查看>>
Mysql的权限管理
查看>>
react 闲谈
查看>>
Java线程入门第二篇
查看>>
VueJS路由
查看>>
bloom filter
查看>>
Boosting算法(一)
查看>>
html格式化
查看>>
TO_DATE函数
查看>>
正则表达式入门
查看>>
Web前端教程2-CSS教程
查看>>
phpstorm常用快捷键
查看>>