精华内容
下载资源
问答
  • React 新版生命周期

    2021-03-30 16:13:55
    与旧版生命周期相比,React生命周期即将废弃componentWillMount()、componentWillReceiveProps()、componentWillUpdate()三个钩子,现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底...

    与旧版生命周期相比,React 生命周期即将废弃componentWillMount()componentWillReceiveProps()componentWillUpdate()三个钩子,现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

    新版增加了两个钩子:getDerivedStateFromProps()getSnapshotBeforeUpdate()

    1. 初始化阶段

    ReactDOM.render()触发

    1. constructor()

    2. getDerivedStateFromProps()

      在调用render()方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新state,如果返回 null 则不更新任何内容

      使用场景(罕见):state的值在任何时候都取决于props

    3. render()

    4. componentDidMount()

      一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息

    2. 更新阶段

    由组件内部this.setSate()或父组件重新render()触发

    1. getDerivedStateFromProps()

    2. shouldComponentUpdate()

    3. render()

    4. getSnapshotBeforeUpdate()

      最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值作为参数传递给 componentDidUpdate()

    5. componentDidUpdate()

    3. 卸载组件

    ReactDOM.unmountComponentAtNode()触发

    1. componentWillUnmount()

      组件即将卸载时触发

      一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

    展开全文
  • react 新版生命周期

    2021-02-23 19:47:00
    React16 之后有三个生命周期被废弃(但并没有删除) componentWillMount componentWillReceiveProps componentWillUpdate 官方计划在17版本完全删除这三个函数,只保留UNSAVE_前缀的三个函数,目的是为了向下兼容,...

    React16 之后有三个生命周期被废弃(但并没有删除)

    1. componentWillMount
    2. componentWillReceiveProps
    3. componentWillUpdate

    官方计划在17版本完全删除这三个函数,只保留UNSAVE_前缀的三个函数,目的是为了向下兼容,但是对于开发者而言应该尽量避免使用他们,而是使用新增的生命周期函数替代它们。

    目前React 16.8+ 的生命周期氛围三个阶段,分别是挂载阶段,更新阶段,卸载阶段

    挂载阶段

    1. constructor: 构造函数,最先被执行,我们通常在构造函数里初始化 state 对象或者给自定义方法绑定this
    2. getDerivedStateFromProps: static getDerivedStateFromProps(nextProps, prevState),这是个静态方法,此方法必须要有返回值,返回一个对象,或者返回 null,返回 null 则不更新任何内容, 当我们接收到新的属性想去修改state, 可以使用 getDerivedStateFromProps
    3. render: render函数是纯函数,只返回需要渲染的东西,不应该包含其他的业务逻辑,可以返回原生的DOM、React 组件、Fragment、Portals、字符串和数字、Boolean 和 null 等内容
    4. componentDidMount: 组件状态之后调用,此时我们可以获取到 DOM 节点并操作,比如对 canvas svg 的操作,服务器请求,订阅都可以写在这里,但是记得要在 componentWillunMount 中取消订阅

    更新阶段

    1. getDerivedStateFormProps: 此方法在更新挂在阶段都可能回调用
    2. shouldComponnetUpdate: shouldComponentUpdate(nextProps, nextState) 有两个参数 nextProps和 nextState, 标识更新的属性和变化之后的 state, 返回一个布尔值,true 标识会触发重新渲染,false 标识不会触发重新渲染,默认返回 true, 我们通常利用此声明周期来优化 React 程序性能。
    3. render: 更新阶段也会触发此生命周期
    4. getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState)这个方法在 render 之后, componentDidUpdate 之前调用,有两个参数 prevProps 和 prevState,标识之前的属性和之前的 state, 这个函数有一个返回值,会作为第三个参数传给 componentDidUpdate,如果不想要返回值, 可以返回 null, 此生命周期必须与 componentDidUpdate 搭配使用
    5. componentDidUpdate: componentDidUpdate(prevProps, prevState, snapshot),该方法在getSnapshotBeforeUpdate方法之后被调用,有三个参数prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的,如果触发某些回调函数时需要用到 DOM 元素的状态,则将对比或计算的过程迁移至 getSnapshotBeforeUpdate,然后在 componentDidUpdate 中统一触发回调或更新状态。

    卸载阶段:

    componentWillUnmount: 会在组件卸载以及销毁之前调用,在此方法中执行必要的清理操作,例如,清除定时器,取消网络请求或者清除在 componentDidMount() 中创建的订阅,清理无效的DOM元素等垃圾清理工作

    异常处理

    1. static getDerivedStateFromError: 此声明周期会在渲染阶段后代组件抛出错误后被调用,他将抛出的错误作为参数,并返回一个值以更新 state
    2. componentDidCatch: 此生命周期在后代组件抛出错误后背调用,他接受两个参数: error —— 抛出的错误。2. info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。componentDidCatch 会在“提交”阶段被调用,因此允许执行副作用。 它应该用于记录错误之类的情况。

    参考React官方文档

    展开全文
  • React新生命周期

    千次阅读 2018-08-14 16:09:53
    react官方打算在未来提出一种实现异步渲染的方法以提高性能,主要的特点就是在渲染完成之前可以被中断,中断之后不会继续执行生命周期,而是重头开始执行生命周期。 所以官方决定,从v17开始删除以下三个生命周期...

    react官方打算在未来提出一种实现异步渲染的方法以提高性能,主要的特点就是在渲染完成之前可以被中断,中断之后不会继续执行生命周期,而是重头开始执行生命周期。

    所以官方决定,从v17开始删除以下三个生命周期钩子:

    componentWillMount
    componentWillReceiveProps
    componentWillUpdate
    

    作为补偿,新增两个新的生命周期钩子

    static getDerivedStateFromProps
    getSnapshotBeforeUpdate
    

    新生命周期钩子

    static getDerivedStateFromProps

    用法:

    • 触发时间:
      • 实例创建之后
      • 每次获取到新的props或者新的state(即setState)之后
    • 参数
      • nextProps
      • nextState
    • 返回值
      • 如果返回一个Object,则相当于进行一次setState操作(注意,这里返回对象虽然改变了state,但不会再次触发此函数)
      • 如果为null,则不更新state
      • 如果无返回值(即默认return undefined),报错
      • 如果返回一个基本类型值(如return 666;),则与返回null无区别

    这里需要注意的是:

    • getDerivedStateFromProps是一个静态方法,this为undefined,不指向实例,所以也拿不到实例的属性和方法。至于为什么要将此方法设计为静态方法,官方文档解释:以后的组件将进行异步渲染,防止实例属性的被不安全访问,编写出异步兼容的代码
    • 此方法不提供一个prevProps的参数,官方解释为,首次执行此方法,prevProps是null,那么每次调用此方法都要判断一次,很耗性能。其次,如果大家以后都习惯没有prevProps的日子,那么react就不保存prevProps的引用了,节省内存,提高性能(心里一万匹***奔腾而过)
    • 如果要访问prevProps,只能将一些props的属性记录到state里面去了
    • 不能同上述提到即将要被删除掉的三个生命周期钩子同时使用

    getSnapshotBeforeUpdate

    用法:

    • 触发时间:update发生的时候,在render之后,在组件dom渲染之前
    • 参数:prevProps, prevState(prevState为上一次更新中getDerivedStateFromProps方法执行后state的值)
    • 返回值可以为任意值,且返回值将作为componentDidUpdate的第三个参数

    这里需要注意的是:

    • 与componentDidUpdate成对使用,否则会报错
    • 不能同上述提到即将要被删除掉的三个生命周期钩子同时使用

    为什么要删除三个生命周期钩子

    其实官方解释是,很多react用户(包括我)都存在错误的使用这三个生命周期钩子的行为,导致以后异步渲染时,会导致极大的性能损耗,所以强制将这三个钩子删除掉(v17版本之后,现在还是可以使用的)。那接下来看看在这三个生命周期到底存在什么错误的用法:

    componentWillMount

    错误做法:

    • 天真地认为在这里请求异步数据,首屏渲染就会有数据了
    • 在此添加事件监听方法
    • 在此初始化state(根据props进行setState)

    缺点:

    • 在此发起异步数据请求之后,会立刻调用render方法,那么首屏渲染还是没有数据
    • 服务器渲染,不会调用componentWillUnmount方法,那么在此钩子里面添加的事件监听方法就无法被浏览器移除,导致内存泄露;同时,在此钩子请求异步数据,也无法首屏渲染数据(原因同上一点),返回到前端还是空白页面。
    • 上面提到多,渲染可被打断,如果被打断,那么就可能会多次调用此钩子,导致多次请求数据,消耗性能

    优化

    • 在constructor里面进行state的初始化
    • 在componentDidMount里面请求异步数据和添加事件监听方法(因为此时能够确保componentWillUnmount钩子一定会执行,就可在这个地方进行销毁事件监听器,回收内存)
    • 解决服务端渲染的问题,可以查阅一下react的同构直出的方法

    componentWillReceiveProps

    错误做法:

    • 根据前后props数据的对比更新state
    • 根据前后props数据的对比请求异步数据

    缺点:

    • 更新state方式不优雅
    • 职能不专,同时进行setState和获取异步数据等会触发新一轮组件更新的操作
    • 渲染可被中断,会多次请求数据

    优化:

    • 使用getDerivedStateFromProps返回值来更新state
    • 在componentDidUpdate获取数据

    componentWillUpdate

    错误做法:

    • 根据新的state发起异步数据请求
    • 在此进行外部函数调用(如nextProps.someMethod())
    • 记录更新前一些节点的属性(这个做法没错,只是现在有更好的方式)

    缺点:

    • 异步数据和外部函数调用请求的缺点同前面两个钩子的一样
    • 记录的信息如果放在state中,需要额外的判断(会进行两次更新)

    优化:

    • 在componentDidUpdate 在此处数据请求和外部函数调用
    • 在getSnapshotBeforeUpdate记录当前节点信息,记录的信息通过返回值传递给componentDidUpdate作为第三个参数(省内存,仅一次更新)

    总结

    新生命周期的思想就是:确保渲染完成之前不做任何会引发重新渲染的操作

    新生命周期流程图(来自react官网)

    最后,附上react rfcs文档地址

    展开全文
  • 生命周期过程 先来看看最新版本react生命周期图: image.png 看看它的变化 新增:getDerivedStateFromProps,getSnapshotBeforeUpdate UNSAFE:UNSAFE_componentWillMount,UNSAFE_componentWillUpdate,...

    新的生命周期过程
    先来看看最新版本react的生命周期图:
    在这里插入图片描述

    image.png
    看看它的变化

    新增:getDerivedStateFromProps,getSnapshotBeforeUpdate
    UNSAFE:UNSAFE_componentWillMount,UNSAFE_componentWillUpdate,UNSAFE_componentWillReceiveProps

    getDerivedStateFromProps
    React生命周期的命名一直都是非常语义化的,这个生命周期的意思就是从props中获取state,可以说是太简单易懂了。

    可以说,这个生命周期的功能实际上就是将传入的props映射到state上面。

    由于16.4的修改,这个函数会在每次re-rendering之前被调用,这意味着什么呢?

    意味着即使你的props没有任何变化,而是父state发生了变化,导致子组件发生了re-render,这个生命周期函数依然会被调用。看似一个非常小的修改,却可能会导致很多隐含的问题。

    使用
    这个生命周期函数是为了替代componentWillReceiveProps存在的,所以在你需要使用componentWillReceiveProps的时候,就可以考虑使用getDerivedStateFromProps来进行替代了。

    两者的参数是不相同的,而getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state。

    需要注意的是,如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾。

    static getDerivedStateFromProps(nextProps, prevState) {
        const {type} = nextProps;
        // 当传入的type发生变化的时候,更新state
        if (type !== prevState.type) {
            return {
                type,
            };
        }
        // 否则,对于state不进行任何操作
        return null;
    }
    

    Case1 – 多来源的不同状态
    假设我们有一个列表,这个列表受到页面主体,也就是根组件的驱动,也受到其本身数据加载的驱动。

    因为这个页面在开始渲染的时候,所有的数据请求可能是通过batch进行的,所以要在根组件进行统一处理,而其列表的分页操作,则是由其本身控制。

    这会出现什么问题呢?该列表的状态受到两方面的控制,也就是re-render可能由props驱动,也可能由state驱动。这就导致了getDerivedStateFromProps会在两种驱动状态下被重新渲染。

    当这个函数被多次调用的时候,就需要注意到,state和props的变化将会怎样影响到你的组件变化。

    // 组件接收一个type参数
    static propTypes = {
        type: PropTypes.number
    }
    
    // 组件还具有自己的状态来渲染列表
    class List extends React.Component {
        constructor(props) {
            super(props);
    
            this.state = {
                list: [],
                type: 0,
            }
        }
    }
    

    如上面代码的例子所示,组件既受控,又控制自己。当type发生变化,会触发一次getDerivedStateFromProps,在这里更新组件的type状态,然而,在进行异步操作之后,组件又会更新list状态,这时你的getDerivedStateFromProps函数就需要注意,不能够仅仅判断type是否变化来更新状态,因为list的变化也会更新到组件的状态。这时就必须返回一个null,否则会导致组件无法更新并且报错。

    Case2 – 组织好你的组件
    考虑一下,如果你的组件内部既需要修改自己的type,又需要接收从外部修改的type。

    是不是非常混乱?getDerivedStateFromProps中你根本不知道该做什么。

    static getDerivedStateFromProps(nextProps, prevState) {
        const {type} = nextProps;
        // type可能由props驱动,也可能由state驱动,这样判断会导致state驱动的type被回滚
        if (type !== prevState.type) {
            return {
                type,
            };
        }
        // 否则,对于state不进行任何操作
        return null;
    }
    

    如何解决这个棘手的问题呢?

    好好组织你的组件,在非必须的时候,摒弃这种写法。type要么由props驱动,要么完全由state驱动。
    如果实在没有办法解耦,那么就需要一个hack来辅助:绑定props到state上。

    constructor(props) {
        super(props);
        this.state = {
            type: 0,
            props,
        }
    }
    static getDerivedStateFromProps(nextProps, prevState) {
        const {type, props} = nextProps;
        // 这段代码可能看起来非常混乱,这个props可以被当做缓存,仅用作判断
        if (type !== props.type) {
            return {
                type,
                props: {
                    type,
                },
            };
        }
        // 否则,对于state不进行任何操作
        return null;
    }
    

    上面的代码可以保证在进行多数据源驱动的时候,状态能够正确改变。当然,这样的代码很多情况下是会影响到别人阅读你的代码的,对于维护造成了非常大的困难。

    从这个生命周期的更新来看,react更希望将受控的props和state进行分离,就如同Redux作者Dan Abramov在redux文档当中写的一样Presentational and Container Components,将所有的组件分离称为展示型组件和容器型组件,一个只负责接收props来改变自己的样式,一个负责保持其整个模块的state。这样可以让代码更加清晰。但是在实际的业务逻辑中,我们有时很难做到这一点,而且这样可能会导致容器型组件变得非常庞大以致难以管理,如何进行取舍还是需要根据实际场景决定的。

    Case3 – 异步
    以前,我们可以在props发生改变的时候,在componentWillReceiveProps中进行异步操作,将props的改变驱动到state的改变。

    componentWillReceiveProps(nextProps) {
        if (props.type !== nextProps.type) {
            // 在这里进行异步操作或者更新状态
            this.setState({
                type: props.type,
            });
            this._doAsyncOperation();
        }
    }
    

    这样的写法已经使用了很久,并且并不会存在什么功能上的问题,但是将componentWillReceiveProps标记为deprecated的原因也并不是因为功能问题,而是性能问题。

    当外部多个属性在很短的时间间隔之内多次变化,就会导致componentWillReceiveProps被多次调用。这个调用并不会被合并,如果这次内容都会触发异步请求,那么可能会导致多个异步请求阻塞。

    getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.

    这个生命周期函数会在每次调用render之前被触发,而读过一点react源码的童鞋都会了解,reactsetState操作是会通过transaction进行合并的,由此导致的更新过程是batch的,而react中大部分的更新过程的触发源都是setState,所以render触发的频率并不会非常频繁(感谢 @leeenx20 的提醒,这里描述进行了修改)。

    在使用getDerivedStateFromProps的时候,遇到了上面说的props在很短的时间内多次变化,也只会触发一次render,也就是只触发一次getDerivedStateFromProps。这样的优点不言而喻。

    那么如何使用getDerivedStateFromProps进行异步的处理呢?

    If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead.

    官方教你怎么写代码系列,但是其实也没有其他可以进行异步操作的地方了。为了响应props的变化,就需要在componentDidUpdate中根据新的props和state来进行异步操作,比如从服务端拉取数据。

    // 在getDerivedStateFromProps中进行state的改变
    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.type !== prevState.type) {
            return {
                type: nextProps.type,
            };
        }
        return null;
    }
    // 在componentDidUpdate中进行异步操作,驱动数据的变化
    componentDidUpdate() {
        this._loadAsyncData({...this.state});
    }
    

    小结
    以上是本期开发过程中使用新的生命周期函数的时候遇到的一点小问题和一些相关思考。react为了防止部分开发者滥用生命周期,可谓非常尽心尽力了。既然你用不好,我就干脆不让你用。一个静态的生命周期函数可以让状态的修改更加规范和合理。

    至于为什么全文没有提到getSnapshotBeforeUpdate,因为自己并没有用到#诚实脸。简单看了一下,这个函数返回一个update之前的快照,并且传入到componentDidUpdate中,组件更新前后的状态都可以在componentDidUpdate中获取了。一些需要在组件更新完成之后进行的操作所需要的数据,就可以不需要挂载到state或者是cache下来了。比如官方例子中所举例的保留更新之前的页面滚动距离,以便在组件update完成之后恢复其滚动位置。也是一个非常方便的周期函数。

    展开全文
  • React新生命周期说明

    2020-07-25 20:07:18
    import React, { Component } from 'react' export default class NewReactComponent extends Component { constructor(props) {//初始化 super(props) // getDefaultProps:接收初始props // getIn
  • 生命周期简单说明 下图已经画的很详细了,简单整理一下每个生命周期的要点。 constructor() constructor(props) React组件的构造函数在挂载之前被调用 static getDerivedStateFromProps() static ...
  • 文章目录新生命周期函数getDerivedStateFromProps实现目标相关代码父组件子组件总结 新生命周期函数getDerivedStateFromProps react 16.3后更新了生命周期函数,不建议使用原来的componentWillReceiveProps、...
  • React 新版生命周期和旧版对比

    千次阅读 2018-05-19 21:44:26
    先mark两张图。以后便于查询 之前: 之后 参考连接这里写链接内容
  • React中的componentWillReceiveProps 的升级版本是: static getDerivedStateFromProps。 getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 ...
  • 作为一个前端开发,从来不能够说自己已经学不动了,的事物每天都在出现,原本已经熟稔的框架也会时不时出来骚扰你一下。 React 16是最近一年多React更新最大的版本。除了让大家喜闻乐见的向下兼容的Fiber,防止了...
  • 前言 日常积累,欢迎指正 正文 需求 有这样一个需求: props.planId 修改就要触发 getPlanDetailByPlanId(planId : string|number) 当然会相应有一个 state.data ,在 get ...在 react 未更新的版本中这种情况在生...
  • React生命周期

    2018-10-14 21:29:40
    提到生命周期,我们首先想到的是从一个程序的产生到消亡,那么React生命周期是什么样子的呢? 在知道React生命周期之前,我们必须得弄明白React是什么? 是什么呢?其实它就是一个用于构建用户界面的...
  • react生命周期钩子函数

    万次阅读 2019-04-22 08:23:35
    掌握单词后会更好理解生命周期: constructor ------构造函数 component ------组件 will ------将要 get ------得到 default ------默认值 initial ------最初的 unsafe ...
  • React-生命周期

    2018-12-02 14:06:44
    React-生命周期 1.react-生命周期可以分为3大块: (1).初试化: componentWillMount() 实例创建完成,且state,props均初始化完成,可以进行访问。 componentDidMount() 实例挂载渲染完成。 注释:初始化...
  • 框架在不断的发展,发现有些生命周期不怎么用的上就直接给去除掉了,发现去除掉后,有些功能的确是没有办法写了,于是又增加了生命周期,但是生命周期用起来比较复杂,直接就出了一些好的模式,直接就可以把...
  • React组件提供了生命周期的钩子函数去响应组件不同时刻的状态,组件的生命周期如下: 实例化 存在期 销毁期 实例化 首次调用组件时,有以下方法会被调用(注意顺序,从上到下先后执行): getDefaultProps ...
  • React Native 生命周期

    千次阅读 2017-08-17 16:01:13
    前言:  在面向对象编程中,任何对象的存在都会存在生命周期。类似我们iOS 的View,就会有LoadView,ViewWillAppear,ViewDidLoad等等生命周期。RN也不例外,这篇主要学习RN的生命周期,...React Native生命周期简介
  • React组件生命周期

    2017-03-21 22:15:39
    React组件生命周期
  • React 5 生命周期

    2017-08-21 17:02:16
    React 4 生命周期生命周期简介组件的生命周期分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移出真实 DOM React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用...
  • react组件生命周期(旧) react组件生命周期()

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,413
精华内容 9,365
关键字:

react新生命周期