使用useEffect模拟组件生命周期

目录
  • useEffect模拟组件生命周期
    • 让函数组件模拟生命周期
    • 初始化
    • 更新阶段
    • 卸载阶段
  • useEffect实现componentWillUnmount生命周期函数
    • 阐述
    • useEffect 解绑副作用
    • useEffect的第二个参数

useEffect模拟组件生命周期

让函数组件模拟生命周期

  • 默认函数组件没有生命周期
  • 函数组件是一个纯函数,执行完即销毁,自己无法实现生命周期
  • 通过Effect hook把生命周期“钩”到纯函数中
    // 模拟 class 组件的 DidMount 和 DidUpdate
    useEffect(() => {
      console.log('在此发送一个 ajax 请求')
    })
 
    // // 模拟 class 组件的 DidMount
     useEffect(() => {
        console.log('加载完了')
     }, []) // 第二个参数是 [] (不依赖于任何 state)
 
     // 模拟 class 组件的 DidUpdate
     useEffect(() => {
         console.log('更新了')
     }, [count, name]) // 第二个参数就是依赖的 state
 
    // 模拟 class 组件的 DidMount
    useEffect(() => {
        let timerId = window.setInterval(() => {
            console.log(Date.now())
        }, 1000)
 
        // 返回一个函数
        // 模拟 WillUnMount 组件销毁的时候 停止计时器
        return () => {
            window.clearInterval(timerId)
        }
    }, [])

总结:

  • 模拟componentDidMount  -  useEffect 依赖 [ ]
  • 模拟compenentDidUpdate - useEffect 无依赖 ,或者 依赖 [a,b,c]
  • 模拟componentWillUnMount - useEffect 中返回一个函数

react在16.8之后有了新特性 react hooks

之前的主要的生命周期为:

初始化

在组件初始化阶段会执行

  • constructor
  • componentWillMount()
  • render()
  • componentDidMount()

更新阶段

props或state的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法:

  • componentWillReceiveProps()
  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()

卸载阶段

  • componentWillUnmount()

useEffect实现componentWillUnmount生命周期函数

阐述

在写React应用的时候,在组件中经常用到 componentWillUnmount 生命周期函数(组件将要被卸载时执行)。比如我们的定时器要清空,避免发生内存泄漏;比如登录状态要取消掉,避免下次进入信息出错。

所以这个生命周期函数也是必不可少的,本文就用 useEffect 来实现这个生命周期函数,并讲解一下 useEffect 容易踩的坑。

useEffect 解绑副作用

学习React Hooks 时,我们要改掉生命周期函数的概念,因为Hooks叫它副作用,所以componentWillUnmount也可以理解成解绑副作用。

这里为了演示用useEffect来实现类似componentWillUnmount效果,先安装React-Router路由,进入项目根本录,使用npm进行安装。

npm install --save react-router-dom@5.2.0

然后打开 Example.js 文件,进行改写代码,先引入对应的React-Router组件。

import { BrowserRouter as Router, Route, Link } from "react-router-dom"

在文件中编写两个新组件,因为这两个组件都非常的简单,所以就不单独建立一个新的文件来写了。

function Index() {
    return <h2>willem</h2>;
}
function List() {
    return <h2>List-Page</h2>;
}

有了这两个组件后,接下来可以编写路由配置,在以前的计数器代码中直接增加就可以了。

function Example(){
    const [count, setCount] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count + 1)}}>Chlick me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    );
}

然后到浏览器中查看一下,看看组件和路由是否可用。

如果可用,我们现在可以调整useEffect了。

在两个新组件中分别加入useEffect()函数:

function Index() {
    useEffect(()=>{
        console.log('useEffect=>我是 Index页面')
    })
    return <h2>willem</h2>;
}
function List() {
    useEffect(()=>{
        console.log('useEffect=>我是 List页面')
    })
    return <h2>List-Page</h2>;
}

这时候我们点击Link进入任何一个组件,在浏览器中都会打印出对应的一段话。这时候可以用返回一个函数的形式进行解绑,代码如下:

function Index() {
    useEffect(()=>{
        console.log('useEffect=>我是Index页面')
        return ()=>{
            console.log('你走了 Index页面')
        }
    })
    return <h2>willem</h2>;
}

这时候你在浏览器中预览,我们仿佛实现了 componentWillUnmount方法。

但这只是好像实现了,当点击计数器按钮时,你会发现你走了Index页面,也出现了。

这到底是怎么回事那?

其实每次状态发生变化,useEffect都进行了解绑。

ReactHooksDemo\demo01\src\Example.js

import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom"
function Index() {
    useEffect(()=>{
        console.log('useEffect=>我是Index页面')
        return ()=>{
            console.log('你走了 Index页面')
        }
    },[])
    return <h2>willem</h2>;
}
function List() {
    useEffect(()=>{
        console.log('useEffect=>我是 List页面')
    })
    return <h2>List-Page</h2>;
}
function Example(){
    const [count, setCount] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count + 1)}}>Chlick me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    );
}
export default Example;

useEffect的第二个参数

那到底要如何实现类似 componentWillUnmount的效果那?

这就需要请出useEffect的第二个参数,它是一个数组,数组中可以写入很多状态对应的变量,意思是当状态值发生变化时,我们才进行解绑。

但是当传空数组 [] 时,就是当组件将被销毁时才进行解绑,这也就实现了componentWillUnmount的生命周期函数。

function Index() {
    useEffect(()=>{
        console.log('useEffect=>我是Index页面')
        return ()=>{
            console.log('你走了 Index页面')
        }
    },[])
    return <h2>willem</h2>;
}

为了更加深入了解第二个参数的作用,把计数器的代码也加上 useEffect 和解绑方法,并加入第二个参数为空数组。

代码如下:

ReactHooksDemo\demo01\src\Example.js

function Example(){
    const [count, setCount] = useState(0);
    useEffect(()=>{
        console.log(`useEffect=>You clicked ${count} times`)
        return ()=>{
            console.log('====================')
        }
    },[])
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count + 1)}}>Chlick me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    );
}

这时候的代码是不能执行解绑副作用函数的。

但是如果我们想每次count发生变化,我们都进行解绑,只需要在第二个参数的数组里加入count变量就可以了。

代码如下:

function Example(){
    const [count, setCount] = useState(0);
    useEffect(()=>{
        console.log(`useEffect=>You clicked ${count} times`)
        return ()=>{
            console.log('====================')
        }
    },[count])
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count + 1)}}>Chlick me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    );
}

这时候只要count状态发生变化,都会执行解绑副作用函数,浏览器的控制台也就打印出了一串=================。

总结

通过对本文的学习,让我们对useEffect函数有了一个比较深入的了解,并且可以通过useEffect实现生命周期函数了,现在用React Hooks这种函数的方法编写组件,对比以前用Class编写组件几乎一样了。

ReactHooksDemo\demo01\src\index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Example from './Example';
ReactDOM.render(<Example />, document.getElementById('root'));

ReactHooksDemo\demo01\src\Example.js

import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom"
function Index() {
    useEffect(()=>{
        console.log('useEffect=>我是Index页面')
        return ()=>{
            console.log('你走了 Index页面')
        }
    },[])
    return <h2>willem</h2>;
}
function List() {
    useEffect(()=>{
        console.log('useEffect=>我是 List页面')
    })
    return <h2>List-Page</h2>;
}
function Example(){
    const [count, setCount] = useState(0);
    useEffect(()=>{
        console.log(`useEffect=>You clicked ${count} times`)
        return ()=>{
            console.log('====================')
        }
    },[count])
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()=>{setCount(count + 1)}}>Chlick me</button>
            <Router>
                <ul>
                    <li><Link to="/">首页</Link> </li>
                    <li><Link to="/list/">列表</Link> </li>
                </ul>
                <Route path="/" exact component={Index} />
                <Route path="/list/" component={List} />
            </Router>
        </div>
    );
}
export default Example;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解React 的数据流和生命周期

    目录 数据流和生命周期 数据和数据流 不可变状态 props 只使用 props 的组件 组件通信 单向数据流 渲染和生命周期 生命周期方法简介 spug 使用了哪些生命周期方法 父子组件的生命周期 数据流和生命周期 如何处理 React 中的数据,组件之间如何通信,数据在 React 中如何流动? 常用的 React 生命周期方法以及开源项目 spug 中使用了哪些生命周期方法? 数据和数据流 虽然也有很多静态网站,但人们使用的大多数网站都充满了随时间变化的数据. state 和 props

  • React useEffect异步操作常见问题小结

    目录 三个常见的问题: 一.react hooks发异步请求 二.如何在组件加载的时候发起异步任务 三.如果在响应回来之前组件被销毁了会怎样? 四.如何在组件交互时发起异步任务 为什么两种写法会有差异呢? 五.其他陷阱 总结 useEffect 和异步任务搭配使用的时候会遇到的一些坑总结. 三个常见的问题: 1.如何在组件加载的时候发起异步任务 2.如何在组件交互的时候发起异步任务 3.其他陷阱 一.react hooks发异步请求 1.使用useEffect发起异步任务,第二个参数使用空数组可

  • React State与生命周期详细介绍

    目录 一.State 1.1 类组件中的State 1.2 函数组件中的State 二.React生命周期 2.1 挂载 2.2 更新 2.3 卸载 2.4 函数式组件useEffect 三.总结 一.State 在React当中,当你更新组件的state,然后新的state就会重新渲染到页面中.在这个时候不需要你操作任何DOM.这和vue中组件的data中的数据是相似的. 1.1 类组件中的State <!DOCTYPE html> <html lang="en"&

  • 使用useEffect模拟组件生命周期

    目录 useEffect模拟组件生命周期 让函数组件模拟生命周期 初始化 更新阶段 卸载阶段 useEffect实现componentWillUnmount生命周期函数 阐述 useEffect 解绑副作用 useEffect的第二个参数 useEffect模拟组件生命周期 让函数组件模拟生命周期 默认函数组件没有生命周期 函数组件是一个纯函数,执行完即销毁,自己无法实现生命周期 通过Effect hook把生命周期“钩”到纯函数中     // 模拟 class 组件的 DidMount 和

  • vue组件生命周期详解

    本文实例为大家分享了vue组件生命周期的具体代码,供大家参考,具体内容如下 分为4个阶段: create/mount/update/destroy 每一个阶段都对应着有自己的处理函数 create: beforeCreate created 初始化 mount: beforeMount mounted 和挂载相关的处理 update: beforeUpdate updated 根据要更新的数据 做逻辑判断 destroy:beforeDestroy destroyed 清理工作 代码: <!do

  • 老生常谈js-react组件生命周期

    组件的生命周期可分成三个状态: •Mounting:已插入真实 DOM •Updating:正在被重新渲染 •Unmounting:已移出真实 DOM 生命周期的方法有: •componentWillMount 在渲染前调用,在客户端也在服务端. •componentDidMount : 在第一次渲染后调用,只在客户端.之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问. 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeou

  • React组件生命周期详解

    调用流程可以参看上图. React组件提供了生命周期的钩子函数去响应组件不同时刻的状态,组件的生命周期如下: 实例化 存在期 销毁期 实例化 首次调用组件时,有以下方法会被调用(注意顺序,从上到下先后执行): getDefaultProps 这个方法是用来设置组件默认的props,组件生命周期只会调用一次.但是只适合react.createClass直接创建的组件,使用ES6/ES7创建的这个方法不可使用,ES6/ES7可以使用下面方式: //es7 class Component { stat

  • 深入理解Vue父子组件生命周期执行顺序及钩子函数

    先附一张官网上的vue实例的生命周期图,每个Vue实例在被创建的时候都需要经过一系列的初始化过程,例如需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等.同时在这个过程中也会运行一些叫做生命周期钩子的函数(回调函数),这给了用户在不同阶段添加自己代码的机会. 1.vue的生命周期图 在vue实例的整个生命周期的各个阶段,会提供不同的钩子函数以供我们进行不同的操作.先列出vue官网上对各个钩子函数的详细解析. 生命周期钩子 生命周期钩子 详细 beforeCreate 在实例

  • 实例讲解React 组件生命周期

    在本章节中我们将讨论 React 组件的生命周期. 组件的生命周期可分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移出真实 DOM 生命周期的方法有: componentWillMount 在渲染前调用,在客户端也在服务端. componentDidMount : 在第一次渲染后调用,只在客户端.之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问. 如果你想和其他JavaScript框架一起使

  • 微信小程序组件生命周期的踩坑记录

    组件生命周期,通常是我们业务逻辑开始的地方. 如果业务场景比较复杂,组件生命周期有不符合预期的表现时, 可能会导致一些诡异的业务bug,它们极难复现和修复. 组件 attached 生命周期执行次数 按照通常的理解,除moved/show/hide等生命周期可能多次执行外, 严格意义上与组件加载相关的生命周期,如:created.attached.ready等,每个组件实例应该只执行一次.但是事实真的如此吗? 背景 这个问题的发现,源于我们在小程序的报错日志中, 收到大量类似Cannot red

  • 详解Angular组件生命周期(一)

    概述 组件声明周期以及angular的变化发现机制 红色方法只执行一次. 变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法. 总共9个方法. 每个钩子都是@angular/core库里定义的接口. import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-life', templateUrl: './life.component.html', styleUrls: ['./life

  • React Class组件生命周期及执行顺序

    一.react组件的两种定义方式 1.函数组件,简单的函数组件像下面这样,接收Props,渲染DOM,而不关注其他逻辑 function Welcome(props) { return <h1>Hello, {props.name}</h1>; } 函数组件无法使用State,也无法使用组件的生命周期方法,没有this,纯展示型组件. 建议:在写组件时,先思考组件应不应该写成展示型组件,能写成展示型组件的尽量写成展示型. 2.class组件,需要继承React.Component,

  • vue组件生命周期钩子使用示例详解

    目录 组件生命周期图 组件生命周期钩子 1.beforeCreate 2.created 3.beforeMount 4.mounted 5.beforeUpdate 6.updated 7.activated 8.deactivated 9.beforeDestroy 10.destroyed 11.errorCaptured 组件生命周期图 组件生命周期钩子 所有的生命周期钩子自动绑定 一.组件的生命周期:一个组件从创建到销毁的整个过程 二.生命周期钩子:在一个组件生命周期中,会有很多特殊的

随机推荐