React生命周期原理与用法踩坑笔记


Posted in Javascript onApril 28, 2020

本文实例讲述了React生命周期原理与用法。分享给大家供大家参考,具体如下:

React生命周期

生命周期概览

生命周期的状态

组件的生命周期可分成三个状态:

  • Mounting:已插入真实 DOM
  • Updating:正在被重新渲
  • Unmounting:已移出真实 DOM
  • componentWillMount 在渲染前调用,在客户端也在服务端。

生命周期介绍

componentDidMount :

在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。

componentWillReceiveProps

在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。

shouldComponentUpdate

返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。

可以在你确认不需要更新组件时使用。

componentWillUpdate

在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。

componentDidUpdate

在组件完成更新后立即调用。在初始化时不会被调用。

componentWillUnmount

在组件从 DOM 中移除之前立刻被调用。

代码示意

class Content extends React.Component {
 componentWillMount() {
   console.log('Component WILL MOUNT!')
 }
 componentDidMount() {
    console.log('Component DID MOUNT!')
 }
 componentWillReceiveProps(newProps) {
    console.log('Component WILL RECEIVE PROPS!')
 }
 shouldComponentUpdate(newProps, newState) {
    return true;
 }
 componentWillUpdate(nextProps, nextState) {
    console.log('Component WILL UPDATE!');
 }
 componentDidUpdate(prevProps, prevState) {
    console.log('Component DID UPDATE!')
 }
 componentWillUnmount() {
     console.log('Component WILL UNMOUNT!')
 }

React16.3生命周期

安装

在创建组件的实例并将其插入DOM时,将按以下顺序调用这些方法:

constructor()

React组件的构造函数在安装之前被调用。在实现React.Component子类的构造函数时,应该super(props)在任何其他语句之前调用。否则,this.props将在构造函数中未定义,这可能导致错误。

通常,在React中,构造函数仅用于两个目的:

通过分配对象来初始化本地状态this.state。

将事件处理程序方法绑定到实例。

不应该打电话setState()给constructor()。相反,如果您的组件需要使用本地状态,请直接在构造函数中指定初始状态this.state。

构造函数是his.state直接分配的唯一位置。在所有其他方法中,需要使用this.setState()。

static getDerivedStateFromProps()

getDerivedStateFromProps在调用render方法之前调用,无论是在初始安装还是后续更新。它应该返回一个更新状态的对象,或者返回null以不更新任何状态。

render()

render()方法是类组件中唯一必需的方法。

调用时,它应检查this.props并this.state返回以下类型之一:

  • React elements。通常通过JSX创建。
  • Arrays and fragments。让您从渲染中返回多个元素。有关更多详细信息,请参阅片段文档。
  • Portals。
  • 字符串和数字。它们在DOM中呈现为文本节点。
  • 布尔或null。什么都没有。

该render()函数应该无状态的,这意味着它不会修改组件状态,每次调用时都返回相同的结果,并且它不直接与浏览器交互。

如果您需要与浏览器进行交互,请执行componentDidMount()或其他生命周期方法。保持render()纯粹使组件更容易思考。

如果shouldComponentUpdate()返回false,则render()不会被调用

componentDidMount()

  • componentDidMount()在安装组件(插入树中)后立即调用。需要DOM节点的初始化应该放在这里。如果需要从远程端点加载数据,这是实例化网络请求的好地方。
  • 此方法是设置任何订阅的好地方。如果您这样做,请不要忘记取消订阅componentWillUnmount()。
  • 您可以在componentDidMount()立即使用this.setState()。它将触发额外的渲染,但它将在浏览器更新屏幕之前发生。这保证即使render()在这种情况下将被调用两次,用户也不会看到中间状态。请谨慎使用此模式,因为它通常会导致性能问题。在大多数情况下,您应该能够分配初始状态constructor()。但是,当您需要在渲染依赖于其大小或位置的东西之前测量DOM节点时,可能需要对模态和工具提示等情况进行处理。

这些方法被认为是遗留的,应该在新代码中避免它们:

UNSAFE_componentWillMount()

更新

props or state 的更改可能导致更新。重新渲染组件时,将按以下顺序调用这些方法:

static getDerivedStateFromProps()
render()
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps, prevState)

getSnapshotBeforeUpdate()在最近呈现的输出被提交到例如DOM之前调用。它使得组件可以在可能更改之前从DOM捕获一些信息(例如滚动位置)。此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。

此用例并不常见,但它可能出现在需要以特殊方式处理滚动位置的聊天线程等UI中。

官网的例子

class ScrollingList extends React.Component {
 constructor(props) {
  super(props);
  this.listRef = React.createRef();
 }

 getSnapshotBeforeUpdate(prevProps, prevState) {
  // Are we adding new items to the list?
  // Capture the scroll position so we can adjust scroll later.
  if (prevProps.list.length < this.props.list.length) {
   const list = this.listRef.current;
   return list.scrollHeight - list.scrollTop;
  }
  return null;
 }

 componentDidUpdate(prevProps, prevState, snapshot) {
  // If we have a snapshot value, we've just added new items.
  // Adjust scroll so these new items don't push the old ones out of view.
  // (snapshot here is the value returned from getSnapshotBeforeUpdate)
  if (snapshot !== null) {
   const list = this.listRef.current;
   list.scrollTop = list.scrollHeight - snapshot;
  }
 }

 render() {
  return (
   <div ref={this.listRef}>{/* ...contents... */}</div>
  );
 }
}

componentDidUpdate()

componentDidUpdate()更新发生后立即调用。初始渲染不会调用此方法。

将此作为在更新组件时对DOM进行操作的机会。只要您将当前道具与之前的道具进行比较(例如,如果道具未更改,则可能不需要网络请求),这也是进行网络请求的好地方。

componentDidUpdate(prevProps) {
 // Typical usage (don't forget to compare props):
 if (this.props.userID !== prevProps.userID) {
  this.fetchData(this.props.userID);
 }
}

componentDidUpdate()但要注意,必须在一个条件下被包裹就像上面的例子中,否则会导致无限循环。它还会导致额外的重新渲染,虽然用户不可见,但会影响组件性能。

componentDidUpdate():如果shouldComponentUpdate()返回false,则不会被调用。

这些方法被认为是遗留的,您应该在新代码中避免它们:

UNSAFE_componentWillUpdate()

UNSAFE_componentWillReceiveProps()

卸载

从DOM中删除组件时调用此方法:

componentWillUnmount()

componentWillUnmount()在卸载和销毁组件之前立即调用。在此方法中执行任何必要的清理,例如使计时器无效,取消网络请求或清除在其中创建的任何订阅componentDidMount()。

不应该调用setState(),componentWillUnmount()因为组件永远不会被重新呈现。卸载组件实例后,将永远不会再次安装它。

错误处理

在渲染期间,生命周期方法或任何子组件的构造函数中发生错误时,将调用这些方法。

static getDerivedStateFromError()

static getDerivedStateFromError(error)

在后代组件抛出错误后调用此生命周期。它接收作为参数抛出的错误,并应返回值以更新状态。

componentDidCatch()

componentDidCatch(error, info)

在后代组件抛出错误后调用此生命周期。它接收两个参数:

error - 抛出的错误。

info- componentStack包含键的对象,其中包含有关哪个组件引发错误的信息。

如果发生错误,可以componentDidCatch()通过调用呈现回退UI setState,但在将来的版本中将不推荐使用。使用static getDerivedStateFromError()处理回退,而不是渲染。

componentDidCatch()在“提交”阶段被调用,因此允许副作用。它应该用于记录错误之类的事情:

class ErrorBoundary extends React.Component {
 constructor(props) {
  super(props);
  this.state = { hasError: false };
 }

 static getDerivedStateFromError(error) {
  // Update state so the next render will show the fallback UI.
  return { hasError: true };
 }

 componentDidCatch(error, info) {
  // Example "componentStack":
  //  in ComponentThatThrows (created by App)
  //  in ErrorBoundary (created by App)
  //  in div (created by App)
  //  in App
  logComponentStackToMyService(info.componentStack);
 }

 render() {
  if (this.state.hasError) {
   // You can render any custom fallback UI
   return <h1>Something went wrong.</h1>;
  }
  return this.props.children; 
 }
}

希望本文所述对大家react程序设计有所帮助。

Javascript 相关文章推荐
javascript的原生方法获取数组中的最大(最小)值
Dec 19 Javascript
jQuery ajax(复习)—Baidu ajax request分离版
Jan 24 Javascript
取消选中单选框radio的三种方式示例介绍
Dec 23 Javascript
简单谈谈javascript中this的隐式绑定
Feb 22 Javascript
jQuery实现产品对比功能附源码下载
Aug 09 Javascript
JS实现六边形3D拖拽翻转效果的方法
Sep 11 Javascript
JavaScript实现简易的天数计算器实例【附demo源码下载】
Jan 18 Javascript
JavaScript实现跟随滚动缓冲运动广告框
Jul 15 Javascript
Easy UI动态树点击文字实现展开关闭功能
Sep 30 Javascript
Angular中管道操作符(|)的使用方法
Dec 15 Javascript
微信小程序开发实现的IP地址查询功能示例
Mar 28 Javascript
微信小程序实现购物车功能
Nov 18 Javascript
js最全的数组的降维5种办法(小结)
Apr 28 #Javascript
JS数组降维的实现Array.prototype.concat.apply([], arr)
Apr 28 #Javascript
React中Ref 的使用方法详解
Apr 28 #Javascript
在Webpack中用url-loader处理图片和字体的问题
Apr 28 #Javascript
react PropTypes校验传递的值操作示例
Apr 28 #Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
Apr 28 #Javascript
Vue + Scss 动态切换主题颜色实现换肤的示例代码
Apr 27 #Javascript
You might like
Re:从零开始的异世界生活 第2季 开播啦
2020/07/24 日漫
php解析url并得到url中的参数及获取url参数的四种方式
2015/10/26 PHP
PHP 实现字符串翻转(包含中文汉字)的实现代码
2017/04/01 PHP
JS localStorage实现本地缓存的方法
2013/06/22 Javascript
JS动态增加删除UL节点LI及相关内容示例
2014/05/21 Javascript
jQuery焦点图切换简易插件制作过程全纪录
2014/08/27 Javascript
javascript获取当前的时间戳的方法汇总
2015/07/26 Javascript
jQuery实现图片上传和裁剪插件Croppie
2015/11/29 Javascript
js实现可控制左右方向的无缝滚动效果
2016/05/29 Javascript
js 自带的 map() 方法全面了解
2016/08/16 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
2016/09/20 Javascript
纯JS实现轮播图
2017/02/22 Javascript
Vue组件化开发思考
2018/02/02 Javascript
node(koa2) web应用模块介绍详解
2019/03/29 Javascript
jQuery zTree插件快速实现目录树
2019/08/16 jQuery
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
js实现踩五彩块游戏
2020/02/08 Javascript
vue使用keep-alive实现组件切换时保存原组件数据方法
2020/10/30 Javascript
[52:06]FNATIC vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Python实现生成随机日期字符串的方法示例
2017/12/25 Python
python代码实现TSNE降维数据可视化教程
2020/02/28 Python
python框架Django实战商城项目之工程搭建过程图文详解
2020/03/09 Python
Python实现一个简单的毕业生信息管理系统的示例代码
2020/06/08 Python
最新Python idle下载、安装与使用教程图文详解
2020/11/28 Python
python的scipy.stats模块中正态分布常用函数总结
2021/02/19 Python
一款纯css3实现的动画加载导航
2014/10/08 HTML / CSS
基于Html5实现的react拖拽排序组件示例
2018/08/13 HTML / CSS
肯尼亚网上商城:Kilimall
2016/08/20 全球购物
继承公证书
2014/04/09 职场文书
建议书的格式
2014/05/12 职场文书
秦始皇兵马俑导游词
2015/02/02 职场文书
小学英语教学反思范文
2016/02/15 职场文书
Golang 编译成DLL文件的操作
2021/05/06 Golang
FP-growth算法发现频繁项集——构建FP树
2021/06/24 Python
Python类方法总结讲解
2021/07/26 Python
vue-cil之axios的二次封装与proxy反向代理使用说明
2022/04/07 Vue.js