React新旧生命周期

184 阅读6分钟

QQ截图20230717161117.jpg

React是一种用于构建用户界面的JavaScript库,它的组件化和声明式编程模型使得开发者能够更高效地构建复杂的应用程序。在React中,组件的生命周期函数起着至关重要的作用,它们在组件的不同阶段被调用,允许开发者在特定的时间点执行相关的逻辑和操作。

然而,自React 16.3版本以后,React引入了新的生命周期函数,并弃用了一些旧的生命周期函数。这一改变引发了开发者对于新旧生命周期函数的关注和讨论。本文将深入探讨React新旧生命周期函数的区别以及如何适应这一变化。

首先,我们将回顾React旧的生命周期函数,包括componentWillMount、componentDidMount、componentWillReceiveProps等等。我们将了解每个函数在组件生命周期中的调用时机和其作用。

然后,我们将介绍React新的生命周期函数,包括getDerivedStateFromProps、getSnapshotBeforeUpdate、componentDidCatch等等。我们将解释这些新函数的用途和用法,并讨论它们相比于旧生命周期函数的优势和改进之处。

接下来,我们将探讨React为什么要引入新的生命周期函数,并讨论这一改变对于组件开发的影响。我们将讨论旧生命周期函数被废弃的原因以及新生命周期函数的设计理念和目标。

最后,我们将分享一些实际的示例和最佳实践,帮助开发者更好地理解和应用新的生命周期函数。我们将探讨如何迁移旧代码来适应新的生命周期函数,并分享一些在组件开发中的常见问题和解决方案。

通过本文的阅读,读者将能够全面了解React新旧生命周期函数的区别和变化,并学会如何适应和应用这一变化来开发更高质量的React应用程序。无论是新手还是有经验的React开发者,本文都将为您提供有价值的知识和实用的技巧。让我们一起深入研究React生命周期函数的世界吧!

旧版

react生命周期(旧).png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React 16.14.1-旧版s</title>
</head>
<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/babel-standalone/7.0.0-beta.3/babel.min.js"></script>
    <!-- 准备一个容器 -->
    <div id="root"></div>
    <script type="text/babel">
        class Person extends React.Component{
            constructor(props){
                super(props);
                console.log("constructor");
                this.state =  {
                    name: "hello",
                    count: 0
                }
            }
            //自定义事件回调
            add = () =>{
                let { count } = this.state;
                this.setState({count: count+1})
            }
            // 自定义事件
            force = () => {
              // 如果调用了 forceUpdate 那么就算阀门关闭也会进行更新钩子的回调
                this.forceUpdate();
            }
            // 自定义事件
            unmount = () =>{
                // 卸载组件的方法
                ReactDOM.unmountComponentAtNode(document.getElementById("root"))
            }
            // 组件将要挂载到页面时调用 
            componentWillMount(){
                console.log("componentWillMount");
            }
            // 组件挂载到页面时调用 1
            componentDidMount(){
                console.log("componentDidMount");
            } 
            // 组件是否应该被更新 控制组件更新的阀门 默认返回为true ; 是否允许setState进行状态值的更新
            shouldComponentUpdate(){
                console.log("shouldComponentUpdate");
                return true;
            }  
            // 组件将要更新
            componentWillUpdate() {
                console.log("componentWillUpdate");
            }
            // 组件已更新的
            componentDidUpdate(){
                console.log("componentDidUpdate");
            }
            // 组件将要卸载时调用
            componentWillUnmount(){
                console.log("componentWillUnmount");
            }
            // 渲染到页面时调用 1+n
            render() {
                console.log("render");
                const {name, count} = this.state;
                return (
                    <div>
                        {name} <br/>
                        <span>count: {count}</span> <br/>
                        <button onClick={this.add}>加一</button>
                        <br/>
                        <button onClick={this.unmount}>卸载组件</button>
                        <button onClick={this.force}>强制更新</button>
                    </div>
                )
            } 
        }
        ReactDOM.render(<Person/>,document.getElementById("root"))
        // console.log("react==",React,ReactDOM);
    </script>
</body>
</html>

生命周期的三个阶段(旧)

1.初始化阶段: 由ReactDOM.render()触发---初次渲染
    1.constructor()
    2.componentWillMount()
    3.render()
    4.componentDidMount()
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1.shouldComponentUpdate()
    2.componentWillUpdate()
    3.render()
    4.componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    1.componentWillUnmount()

新版

react生命周期(新).png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react生命周期17.0.1</title>
</head>
<body>
    <!-- 准备一个容器 -->
    <div id="root"></div>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <!-- jsx语法 -->
    <script type="text/babel">
        // console.log("React",React.version);
        class Count extends React.Component{

            // 初始化state
            state = {count:0};
            // 自定义事件
            add = () => {
                let { count } = this.state;
                this.setState({
                    count: ++count
                });
            }
            // 若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
            static getDerivedStateFromProps(props,state){
                console.log("getDerivedStateFromProps",props,state);
                return 100;
            }
            // 在更新之前获取快照
            getSnapshotBeforeUpdate(){
                console.log("getSnapshotBeforeUpdate");
                return "hello";
            }
            componentDidUpdate(preProps,preState,value){
                console.log("componentDidUpdate",preProps,preState,value);
            }
            componentDidMount(){
                console.log("componentDidMount");
            }
            // render函数
            render(){
                console.log("render");
                const {count} = this.state
                return (
                    <div>
                        <h2>count: {count}</h2>
                        <button onClick={this.add}>+1</button>
                    </div>
                )
            }
            
        }
        ReactDOM.render(<Count name="handsome"/>,document.getElementById("root"))
    </script>
</body>
</html>

生命周期的三个阶段(新)

  1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    1. constructor()
    2. getDerivedStateFromProps
    3.render()
    4.componentDidMount()
  1. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1. getDerivedStateFromProps;
    2. shouldComponentUpdate();
    3. render();
    4. getSnapshotBeforeUpdate;
    5. componentDidUpdate()

3.卸载组件:由ReactDOM.unmountComponentAtNode()触发

    1.componentWillUnmount()

2.2. 重要的勾子

1.render:初始化渲染或更新渲染调用
2.componentDidMount:开启监听, 发送ajax请求
3.componentWillUnmount:做一些收尾工作, 如: 清理定时器

2.3. 即将废弃的勾子

1.componentWillMount
2.componentWillReceiveProps
3.componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

旧生命周期函数:

  1. componentWillMount:在组件被渲染之前调用,适合执行一些准备工作,但不建议在此处进行数据的获取和更新操作。
  2. componentDidMount:在组件渲染完成后调用,可以进行DOM操作、数据的获取和更新等异步操作。
  3. componentWillReceiveProps:在组件接收到新的props时调用,可以根据新的props来更新组件的状态。
  4. shouldComponentUpdate:在组件接收到新的props或者state时调用,用于决定是否重新渲染组件,默认情况下每次接收到新的props或者state都会触发重新渲染。
  5. componentWillUpdate:在组件即将更新时调用,可以进行一些准备工作,但不建议进行数据的获取和更新操作。
  6. componentDidUpdate:在组件完成更新后调用,可以进行DOM操作、数据的获取和更新等异步操作。
  7. componentWillUnmount:在组件即将被卸载和销毁之前调用,可以进行一些清理操作,如取消定时器、移除事件监听等。

新生命周期函数:

  1. static getDerivedStateFromProps:在组件接收到新的props时调用,用于根据新的props计算并返回新的状态,常用于替代componentWillReceiveProps。
  2. getSnapshotBeforeUpdate:在组件即将更新时调用,用于获取更新前的DOM状态,常用于配合componentDidUpdate进行一些DOM操作。
  3. componentDidCatch:在子组件抛出异常时调用,用于捕获和处理错误,可以展示错误信息或者进行日志记录等。

新生命周期函数的变化和优势:

  1. 简化和明确:新的生命周期函数将旧的生命周期函数进行了拆分和重命名,使得组件的生命周期更加清晰和易于理解。
  2. 更好的错误处理:引入了componentDidCatch函数,使得在组件内部发生的错误可以被捕获并进行相应的处理,避免了错误的蔓延。
  3. 更好的性能优化:新生命周期函数的引入使得开发者更容易决定是否需要重新渲染组件,从而提升了React应用的性能。

总的来说,新旧生命周期函数都有各自的作用和功能,旧生命周期函数在React的早期使用较多,而新生命周期函数则在React的进一步发展中引入,为开发者提供了更好的控制和优化组件的能力。了解新旧生命周期函数的区别和用法,对于开发高质量的React应用程序非常重要。