欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-25 17:50:23
本文实例讲述了react生命周期原理与用法。分享给大家供大家参考,具体如下:react生命周期生命周期概览生命周期的状态组件的生命周期可分成三个状态: mounting:已插入真实 dom upd...

本文实例讲述了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程序设计有所帮助。