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 相关文章推荐
JS 中document.URL 和 windows.location.href 的区别
Nov 11 Javascript
网站繁简切换的JS遇到页面卡死的解决方法
Mar 12 Javascript
javascript 获取元素样式必杀技
May 04 Javascript
纯JS打造网页中checkbox和radio的美化效果
Oct 13 Javascript
Javascript DOM事件操作小结(监听鼠标点击、释放,悬停、离开等)
Jan 20 Javascript
canvas实现图像放大镜
Feb 06 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
Jun 15 Javascript
详解swiper在vue中的应用(以3.0为例)
Sep 20 Javascript
vue根据值给予不同class的实例
Sep 29 Javascript
简单说说如何使用vue-router插件的方法
Apr 08 Javascript
解决vue语法会有延迟加载显现{{xxx}}的问题
Nov 14 Javascript
vue-cli在 history模式下的配置详解
Nov 26 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
十天学会php之第二天
2006/10/09 PHP
浅谈PHP中try{}catch{}的使用方法
2016/12/09 PHP
php+js实现裁剪任意形状图片
2018/10/31 PHP
关于php unset对json_encode的影响详解
2018/11/14 PHP
php利用ZipArchive类操作文件的实例
2020/01/21 PHP
javascript URL锚点取值方法
2009/02/25 Javascript
jquery等待效果示例
2014/05/01 Javascript
Redis基本知识、安装、部署、配置笔记
2015/03/05 Javascript
JQuery插入DOM节点的方法
2015/06/11 Javascript
使用ngView配合AngularJS应用实现动画效果的方法
2015/06/19 Javascript
基于jQuery实现select下拉选择可输入附源码下载
2016/02/03 Javascript
不使用script导入js文件的几种方法
2016/10/27 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
vue移动UI框架滑动加载数据的方法
2018/03/12 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
2018/04/01 Javascript
layui 中select下拉change事件失效的解决方法
2019/09/20 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
Python数据可视化编程通过Matplotlib创建散点图代码示例
2017/12/09 Python
python机器学习案例教程——K最近邻算法的实现
2017/12/28 Python
python实现简易通讯录修改版
2018/03/13 Python
Pandas中把dataframe转成array的方法
2018/04/13 Python
Python实现将数据写入netCDF4中的方法示例
2018/08/30 Python
简单了解Django应用app及分布式路由
2019/07/24 Python
Python实现微信好友的数据分析
2019/12/16 Python
美国第二大团购网站:LivingSocial
2016/07/24 全球购物
露营世界:Camping World
2017/02/02 全球购物
Marc O’Polo俄罗斯官方在线商店:德国高端时尚品牌
2019/12/26 全球购物
Vuori官网:运动服装的终级表现
2021/01/27 全球购物
简单说下OSPF的操作过程
2014/08/13 面试题
精通CAD能手自荐书
2014/01/31 职场文书
学习“七一”讲话精神体会
2014/07/08 职场文书
思想纪律作风整顿剖析材料
2014/10/11 职场文书
初中信息技术教学反思
2016/02/16 职场文书
只需要12页,掌握撰写一流商业计划书的技巧
2019/05/07 职场文书
Golang Gob编码(gob包的使用详解)
2021/05/07 Golang
Apache Hudi 加速传统的批处理模式
2022/04/24 Servers