React Hook中的useEffecfa函数的使用小结

目录
  • useEffect的详细解析
    • useEffecf基本使用
    • 清除副作用(Effect)
    • 使用多个useEffect
    • useEffect性能优化

useEffect的详细解析

useEffecf基本使用

书接上文, 上一篇文章我们讲解了State Hook, 我们已经可以通过这个hook在函数式组件中定义state

我们知道在类组件中是可以有生命周期函数的, 那么如何在函数组件中定义类似于生命周期这些函数呢?

Effect Hook 可以让你来完成一些类似于class中生命周期的功能;

事实上,类似于网络请求、手动更新DOM、一些事件的监听,都是React更新DOM的一些副作用(Side Effects);

所以对于完成这些功能的Hook被称之为 Effect Hook;

假如我们现在有一个需求:页面中的title总是显示counter的数字,分别使用class组件和Hook实现:

类组件实现

import React, { PureComponent } from 'react'

export class App extends PureComponent {
  constructor() {
    super()

    this.state = {
      counter: 100
    }
  }

  // 进入页面时, 标题显示counter
  componentDidMount() {
    document.title = this.state.counter
  }

  // 数据发生变化时, 让标题一起变化
  componentDidUpdate() {
    document.title = this.state.counter
  }

  render() {
    const { counter } = this.state

    return (
      <div>
        <h2>{counter}</h2>
        <button onClick={() => this.setState({counter: counter+1})}>+1</button>
      </div>
    )
  }
}

export default App

函数组件加Hook的实现:

  • 通过useEffect这个Hook,可以告诉React需要在渲染后执行某些操作;
  • useEffect要求我们传入一个回调函数,在React执行完更新DOM操作之后(也就是组件被渲染完成后),就会回调这个函数;
  • 默认情况下,无论是第一次渲染之后,还是每次更新之后,都会执行这个回调函数; 一般情况下我们在该回调函数中都是编写副作用的操作(例如网络请求, 操作DOM, 事件监听)
  • 因此需要注意的是, 有许多说法说useEffect就是用来模拟生命周期的, 其实并不是; useEffect可以做到模拟生命周期, 但是他主要的作用是用来执行副作用的

因此需要注意的是, 有许多说法说useEffect就是用来模拟生命周期的, 其实并不是; useEffect可以做到模拟生命周期, 但是他主要的作用是用来执行副作用的

import React, { memo, useEffect, useState } from 'react'

const App = memo(() => {
  const [counter, setCounter] = useState(200)

  // useEffect传入一个回调函数, 在页面渲染完成后自动执行
  useEffect(() => {
    // 一般在该回调函数在编写副作用的代码(网络请求, 操作DOM, 事件监听)
    document.title = counter
  })

  return (
    <div>
      <h2>{counter}</h2>
      <button onClick={() => setCounter(counter+1)}>+1</button>
    </div>
  )
})

export default App

清除副作用(Effect)

在class组件的编写过程中,某些副作用的代码,我们需要在componentWillUnmount中进行清除:

比如我们之前的事件总线或Redux中手动调用subscribe;

都需要在componentWillUnmount有对应的取消订阅;

Effect Hook通过什么方式来模拟componentWillUnmount呢?

useEffect传入的回调函数A本身可以有一个返回值,这个返回值是另外一个回调函数B:

type EffectCallback = () => (void | (() => void | undefined));

为什么要在 effect 中返回一个函数?

这是 effect 可选的清除机制。每个 effect 都可以返回一个清除函数;

如此可以将添加和移除订阅的逻辑放在一起;

它们都属于 effect 的一部分;

React 何时清除 effect?

React 会在组件更新和卸载的时候执行清除操作, 将上一次的监听取消掉, 只留下当前的监听 ;

正如之前学到的,effect 在每次渲染的时候都会执行;

import React, { memo, useEffect } from 'react'

const App = memo(() => {
  useEffect(() => {
    // 监听store数据发生改变
    const unsubscribe = store.subscribe(() => {

    })

    // 返回值是一个回调函数, 该回调函数在组件重新渲染或者要卸载时执行
    return () => {
      // 取消监听操作
      unsubscribe()
    }
  })

  return (
    <div>
      <h2>App</h2>
    </div>
  )
})

export default App

使用多个useEffect

使用Hook的其中一个目的就是解决class中生命周期经常将很多的逻辑放在一起的问题:

比如网络请求、事件监听、手动修改DOM,这些往往都会放在componentDidMount中;

一个函数组件中可以使用多个Effect Hook,我们可以将逻辑分离到不同的useEffect中:

import React, { memo, useEffect } from 'react'

const App = memo(() => {
  // 监听的useEffect
  useEffect(() => {
    console.log("监听的代码逻辑")

    return () => {
      console.log("取消的监听代码逻辑")
    }
  })

  // 发送网络请求的useEffect
  useEffect(() => {
    console.log("网络请求的代码逻辑")
  })

  // 操作DOM的useEffect
  useEffect(() => {
    console.log("操作DOM的代码逻辑")
  })

  return (
    <div>
      App
    </div>
  )
})

export default App

Hook允许我们按照代码的用途分离它们, 而不是像生命周期函数那样, 将很多逻辑放在一起:

React将按照 effect 声明的顺序依次调用组件中的每一个 effect;

useEffect性能优化

默认情况下,useEffect的回调函数会在每次渲染时都重新执行,但是这会导致两个问题:

某些代码我们只是希望执行一次即可(比如网络请求, 组件第一次渲染中执行一次即可, 不需要执行多次),类似于类组件中的componentDidMount和componentWillUnmount中完成的事情;

另外,多次执行也会导致一定的性能问题;

我们如何决定useEffect在什么时候应该执行和什么时候不应该执行呢?

useEffect实际上有两个参数:

  • 参数一: 执行的回调函数, 这个参数我们已经使用过了不再多说;
  • 参数二: 是一个数组类型, 表示 该useEffect在哪些state发生变化时,才重新执行;(受谁的影响才会重新执行)

案例练习:

受count影响的Effect;

import React, { memo, useEffect, useState } from 'react'

const App = memo(() => {
  const [counter, setCounter] = useState(100)

  // 发送网络请求的useEffect, 只有在counter发生改变时才会重新执行
  useEffect(() => {
    console.log("网络请求的代码逻辑")
  }, [counter])

  return (
    <div>
      <h2 onClick={() => setCounter(counter+1)}>{counter}</h2>
    </div>
  )
})

export default App

但是,如果一个函数我们不希望依赖任何的内容时,也可以传入一个空的数组 []:

那么这里的两个回调函数分别对应的就是componentDidMount和componentWillUnmount生命周期函数了;

import React, { memo, useEffect, useState } from 'react'

const App = memo(() => {
  const [counter, setCounter] = useState(100)

  // 传入空数组表示不受任何数据依赖
  useEffect(() => {
    // 此时传入的参数一这个回调函数: 相当于componentDidMount
    console.log("监听的代码逻辑")

    // 参数一这个回调函数的返回值: 相当于componentWillUnmount
    return () => {
      console.log("取消的监听代码逻辑")
    }
  }, [])

  return (
    <div>
      <h2 onClick={() => setCounter(counter+1)}>{counter}</h2>
    </div>
  )
})

export default App

总结: useEffect可以模拟之前的class组件的生命周期(类似而不是相等), 并且它比原来的生命周期更加强大, 青出于蓝而胜于蓝

到此这篇关于React Hook  useEffecfa函数的使用细节详解的文章就介绍到这了,更多相关React Hook  useEffecfa函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React Hook中的useState函数的详细解析

    useState => 让函数组件具有维持状态的能力useState 这个 Hook 是用来管理 state 的,它可以让函数组件具有维持状态的能力.即在一个函数组件的多次渲染之间,这个 state 是共享的. Hooks 的最大的作用就是可以让你在不编写class的情况下使用state以及其他的 React 特性 useState的详细解析 在上一篇文章中, 我用到useState来让大家体验一下hooks函数 import { memo, useState } from "react&

  • React Hook父组件如何获取子组件的数据/函数

    目录 React Hook父组件获取子组件数据/函数 子组件MyWorldMap 父组件MyTrip React Hook父组件提交子组件form 父组件 子组件 React Hook父组件获取子组件数据/函数 我们知道在react中,常用props实现子组件数据到父组件的传递,但是父组件调用子组件的功能却不常用. 文档上说ref其实不是最佳的选择,但是想着偷懒不学redux,在网上找了很多教程,要不就是hook的讲的太少,要不就是父子组件傻傻分不清,于是只好再啃了一下文档,就学了一下其它hoo

  • React函数式组件Hook中的useState函数的详细解析

    目录 前言 一.什么是函数式组件 二.useState 前言 公司项目需要使用react,而函数式组件也是官方比较推荐的!!!所以学习hooks是很重要的. 一.什么是函数式组件 纯函数组件有以下特点: 没有状态 没有生命周期 没有 this 因存在如上特点,使得纯函数组件只能做UI展示的功能, 涉及到状态的管理与切换就不得不用到类组件或者redux. 但因为简单的页面也是用类组件,同时要继承一个React实例,使得代码会显得很重. 以前我们可以使用class来声明一个组件,其实使用functi

  • React函数式组件Hook中的useEffect函数的详细解析

    目录 前言 useEffect的作用 useEffect的使用? 1.class组件 2.函数式组件 总结 前言 React函数式编程没有生命周期,因此需要借助useEffect来实现. useEffect的作用 发ajax请求获取数据 设置订阅/获取定时器 手动更改真实DOM useEffect的使用? 1.class组件 在class组件中可以使用生命周期函数,知道组件触发的过程. 代码如下(示例): import React, { Component } from 'react' expo

  • React函数组件hook原理及构建hook链表算法详情

    目录 写在前面的小结 Demo fiber hook 链表 hook 对象及其属性介绍 useState Hook 对象 useRef Hook useEffect.useLayoutEffect 以及 useImperativeHandle useMemo useCallback 构建 Hook 链表的源码 renderWithHooks 函数组件执行 构建 hook 链表的算法 mountWorkInProgressHook 构建 hook 链表算法 updateWorkInProgress

  • React Hook中的useEffecfa函数的使用小结

    目录 useEffect的详细解析 useEffecf基本使用 清除副作用(Effect) 使用多个useEffect useEffect性能优化 useEffect的详细解析 useEffecf基本使用 书接上文, 上一篇文章我们讲解了State Hook, 我们已经可以通过这个hook在函数式组件中定义state 我们知道在类组件中是可以有生命周期函数的, 那么如何在函数组件中定义类似于生命周期这些函数呢? Effect Hook 可以让你来完成一些类似于class中生命周期的功能; 事实上

  • React Hook中useState更新延迟问题及解决

    目录 React Hook中useState更新延迟 React Hook useState连续更新对象问题 React Hook中useState更新延迟 方法一:去掉useEffect的第二个参数 例如以下代码 错误实例 const[zoom, setZoom] = useState(0); useEffect(() = >{     document.getElementById('workspace-content').addEventListener('mousewheel', scr

  • sqlserver中的自定义函数的方法小结

    "自定义函数"是我们平常的说法,而"用户定义的函数"是 SQL Server 中书面的说法. SQL Server 2000 允许用户创建自定义函数,自定义函数可以有返回值. 自定义函数分为:标量值函数或表值函数 如果 RETURNS 子句指定一种标量数据类型,则函数为标量值函数.可以使用多条 Transact-SQL 语句定义标量值函数. 如果 RETURNS 子句指定 TABLE,则函数为表值函数. 表值函数又可分为:内嵌表值函数(行内函数)或多语句函数 如果

  • React项目中hook实现展示对话框功能

    目录 思路:使用全局状态管理所有对话框 尝试设计一个API去做对话框的全局管理 实现:创建NiceModal组件和相关API 处理对话框的返回值 总结 React中使用对话框并不容易,主要因为: 对话框需要在父组件中声明,才能在子组件中控制其是否显示 给对话框传递参数只能由props传入,这意味着所有状态管理都必须在更高阶的组件中.而实际上这个对话框的参数只在子组件中才会维护.这时就需要我们使用自定义事件将参数传回 这些问题的本质就是:如何用一个统一的方式去管理对话框,从而让对话框相关的业务逻辑

  • 详解React中setState回调函数

    在使用React过程中,中可以使用this.state来访问需要的某些状态,但是需要更新或者修改state时,一般而言,我们都会使用setState()函数,从而达到更新state的目的,setState()函数执行会触发页面重新渲染UI.但是!!!setState是异步的!!! 1. 语法: setState(updater[, callback]) // updater是要改变的state对象,callback是state导致的页面重新渲染的回调,等价于componentDidUpdate

  • React中使用setInterval函数的实例

    本文是基于Windows 10系统环境,学习和使用React:Windows 10 一.setInterval函数 (1) 定义 setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭.由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数. (2) 实例 import React, { Component } fr

随机推荐