React新旧版本对比总结归纳(生命周期篇)

生命周期

我们先来看下React16.0前后生命周期变化的图片

生命周期图谱:http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

16.0版本前
16.0版本后

❶ 过时生命周期:

① componentWillMount

② componentWillReceiveProps

③ componentWillUpdate

❷ 即将过时生命周期:(在新代码中我们应该避免使用它们)

① UNSAFE_componentWillMount

② UNSAFE_componentWillReceivePorps

③ UNSAFE_componentWillUpdate

❸ 新增生命周期

① getDerivedStateFromProps

② getSnapShotBeforeUpdate

③ getDerivedStateFromError

④ componentDidCatch

老生命周期我就不赘述了,下边我归纳下我对几个新生命周期用法的理解

① static getDerivedStateFromProps(nextProps, prevState)

○ 什么时候调用?

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

○ 返回值

返回值是必须的,它应该是一个对象,用于更新state; 如果返回值为null,state不更新。

○ 主要用途?

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

特别说明:

它是静态方法,所以它没有this(实例对象无法访问),只能通过类名访问。

看下边例子就明白了!

class Child extends Component {

    constructor(props) {

        super(props);

        this.state= {

            info: props.info || "hello world"

        }

}

    static getDerivedStateFromProps(nextProps, prevState) {

        if (nextProps.info!== prevState.info) {

            return ({

                info: nextProps.info

            })

        }

        return null;

    }

    render() {

        return (

            <p>{this.state.info}</p>

                    )

       }

 }

class App extends Component {

    constructor(props) {

        super(props);

        this.state= {

            childInfo: "Hello world"

        }

    }

    clickHandler = () => {

        this.setState({

            childInfo: "Changed world"

        })

    };

    render() {

        return (

            <>

                <Child info={this.state.childInfo}/>

                <button onClick={this.clickHandler}>Click Me</button>

            </>

        );

    }

}

② getSnapshotBeforeUpdate(prevProps, prevState)

○ 什么时候调用?

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。

○ 返回值

应返回 snapshot 的值(或 null)

○ 有什么用途?

它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

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

③ static getDerivedStateFromError(error)

○ 什么时候调用?

此生命周期会在渲染阶段后代组件抛出错误后被调用,因此不允许出现副作用。

○ 返回值

它将抛出的错误作为参数,并返回一个值以更新 state

○ 有什么用途?

主要用于封装错误边界用,收集错误信息并做对应处理。

以下为具体用法用例

class ErrorBoundary extends React.Component {

    constructor(props) {

        super(props);

        this.state= {hasError: false};

    }

    static getDerivedStateFromError(error) {

        // 更新 state 使下一次渲染可以显降级UI

        return {hasError: true};

    }

    render() {

        if (this.state.hasError) {

            // 你可以渲染任何自定义的降级UI

            return <h1>Something went wrong.</h1>;

        }

        return this.props.children;

    }

}

然后你可以将它作为一个常规组件去使用:

<ErrorBoundary>

    <div>Hello world</div>

</ErrorBoundary>

④ componentDidCatch(error, info)

○ 什么时候调用?

此生命周期会在“提交”阶段后代组件抛出错误后被调用,因此允许执行副作用。

○ 参数

error —— 抛出的错误。

info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。

○ 返回值

它将抛出的错误作为参数,并返回一个值以更新 state

○ 有什么用途?

主要用于封装错误边界用,收集错误信息并做对应处理。

用例如下:

class ErrorBoundary extends React.Component {

    constructor(props) {

        super(props);

        this.state= { hasError: false };

    }

    static getDerivedStateFromError(error) {

        // 更新 state 使下一次渲染可以显示降级UI

        return { hasError: true };

    }

    componentDidCatch(error, info) {

        // "组件堆栈" 例子:

//  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) {

            // 你可以渲染任何自定义的降级UI

            return <h1>Something went wrong.</h1>;

        }

        return this.props.children;

    }

}

特别注意:

如果发生错误,你可以通过调用 setState 使用 componentDidCatch() 渲染降级 UI,但在未来的版本中将不推荐这样做。 可以使用静态 getDerivedStateFromError() 来处理降级渲染。

结论:对于新生命周期③和④作用基本是一致的,都是用于封装错误边界,收集边界下后代组件构造函数中发生的错误信息并作出对应处理。不同的是调用时间和返回参数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348