React中useLayoutEffect钩子使用场景详解

目录
  • 简介
  • useEffect钩子的概述
    • 钩子流程
  • useLayoutEffect钩子的概述
    • 钩子流程
  • 什么时候使用useLayoutEffect钩子?
  • 总结

简介

不久前,React对其功能组件进行了一次重大更新(在2019年3月的16.8版本中),终于为这些组件提供了一种变得有状态的方法。

钩子的加入不仅意味着功能组件将能够提供自己的状态,而且还能通过引入useEffect钩子来管理自己的生命周期事件。

此外,这次更新还引入了一个全新的useLayoutEffect钩子,根据React文档,它的作用与[useEffect](upmostly.com/tutorials/i… in a new tab)钩子的作用相当相似;所以这就引出了一个问题。 两者之间到底有什么区别?

如果你对钩子还不熟悉,我建议你去看看 这篇文章在那里你会很好地了解它们是什么,它们的用途,以及你如何在你的应用程序中使用它们。

在这篇文章中,我们将更深入地探讨每个钩子的作用,两者之间的区别是什么,到最后,你应该对它们各自的工作原理有更好的理解,什么时候应该使用其中一个而不是另一个,以及爱上其中一个的一些常见陷阱。

useEffect钩子的概述

这个钩子最初是作为处理功能组件中的副作用的另一种方式添加的,类似于基于类的组件中的componentDidMount和componentDidUpdate方法(它们也是在同一时间运行的)。

因此,它在基于类的组件中的等价物是componentDidMount、componentDidUpdate 和 componentWillUnmount方法的组合,后者是作为参数传递给钩子的回调语句中的一个效果。

钩子流程

  • 你以某种方式引起渲染(状态被更新或父类重新渲染)。
  • React渲染你的组件(调用它)
  • 屏幕得到视觉上的更新
  • 然后运行useEffect

useLayoutEffect钩子的概述

与useEffect类似,它与Class Components中的componentDidMount和componentDidUpdate同时运行。然而,useLayoutEffect是同步运行的,与useEffect相反,这意味着它收到的回调只有在组件中进行了V-DOM计算之后,但在它们被绘制到实际的DOM之前才会被调用。

这意味着,如果我们确实需要对任何DOM元素进行任何JavaScript查询,useLayoutEffect是我们可能需要的钩子。

钩子流程

  • 你以某种方式导致渲染(改变状态,或者父类重新渲染)。
  • React渲染你的组件(调用它)
  • useLayoutEffect运行,React等待它完成。
  • 屏幕在视觉上被更新

什么时候使用useLayoutEffect钩子?

在使用useEffect钩子时,有一个常见的问题,即当一个组件的状态被更新时,它可能会 "闪动"。这是因为组件在继续进行异步计算的过程中,首先会以部分就绪的状态进行渲染,然后才会以最终的状态进行重新渲染。

这是一个很好的指示,你可能想使用useLayoutEffect钩子来代替。

这样的例子是试图在点击一个按钮时生成并渲染一个极高的数值,就像这个例子中一样:

import { useState, useEffect } from 'react';
import './App.css';
function App() {
  const [value, setValue] = useState(0);
  useEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);
  console.log('render', value);
  return (
    <div className="App">
      <p>Value: {value}</p>
      <button onClick={() => setValue(0)}>
        Generate Random Value
      </button>
    </div>
  );
}
export default App;

如果我们要检查我们的应用程序是如何表现的,我们将看到每次我们按下按钮时一个不断变化的闪烁的数字。

状态更新时闪烁的组件

如果我们使用useLayoutEffect钩子,我们就可以摆脱这个视觉错误。

import { useState, useLayoutEffect } from 'react';
import './App.css';
function App() {
  const [value, setValue] = useState(0);
  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);
  console.log('render', value);
  return (
    <div className="App">
      <p>Value: {value}</p>
      <button onClick={() => setValue(0)}>
        Generate Random Value
      </button>
    </div>
  );
}
export default App;

而且,你可以从最后一个视频样本中看到,我们已经能够摆脱闪烁的效果了。

这是因为这两个钩子的行为略有不同;第一个钩子是异步处理计算和DOM渲染的,而后者是先进行计算,然后才处理计算结果在屏幕上的渲染。

在我们的例子中,这意味着useEffect钩子正试图生成随机值,并同时将其渲染到屏幕上。另一方面,useLayoutEffect钩子试图首先完成计算,然后才向我们展示生成的数字。

总结

正如你所注意到的,useLayoutEffect钩子为我们提供了一个干净的解决方案,以解决我们可能发现自己经常与之斗争的问题,那就是被React同时处理DOM绘制和计算的方式所纠缠。

作为一个启示,当你在处理 ref 值或需要做任何类型的工作,围绕着通过vanilla JavaScript方法(如querySelector、querySelectorAll或任何其他方式)查询DOM元素时,你可能想使用useLayoutEffect钩。

请记住,尽管useLayoutEffect钩子为我们提供了很多有用的东西,但在99%的情况下,你最好还是使用useEffect钩子,因为它由于其异步的性质,常常会有更高的性能。

所以,就这样了。

希望你现在已经对这两个钩子的用法有了更好的理解,以及每个钩子可能派上用场的场景;这也是特别常见的,因为它被使用得相当少,要么是由于开发者不知道它,要么是知道它,但不确定它的具体作用。

以上就是React中useLayoutEffect钩子使用场景详解的详细内容,更多关于React useLayoutEffect钩子的资料请关注我们其它相关文章!

(0)

相关推荐

  • React中useEffect与生命周期钩子函数的对应关系说明

    目录 React useEffect与生命周期钩子函数的对应关系 使用格式一:不带参数的情况 使用格式二:带第二个参数,参数为空数组 使用格式三:带第二个参数,并且指定了依赖项 使用格式四:依赖项为空,没有具体的副作用函数.但是有副作用函数的清理函数. React函数式组件用useEffect模拟三个生命周期钩子函数 React useEffect与生命周期钩子函数的对应关系 在React的函数组件中,useEffect的作用其实也对标了类组件中的生命周期,它的四种使用格式也与生命周期的四种钩子

  • 解析react 函数组件输入卡顿问题 usecallback react.memo

    目录 现象 分析 解决 方案一: 方案二: 弊端 现象 在输入问题时,输入框响应巨慢. 效果图 分析 右侧控制台显示,子组件不停在mount unmount,子组件中使用了CKEditor组件,每次mount开支较大,导致输入卡顿 代码如下: const qdata = (q.qdata || [ { id: getQuestionId('OPTION') }, { id: getQuestionId('OPTION') }, ]) as SelectOption[]; const render

  • 关于react中useCallback的用法

    目录 基础用法 父组件 子组件 useCallback是react中比较重要的一个hook useCallback 用来返回一个函数,在父子组件传参或者通用函数封装中,起到举足轻重的作用. 基础用法 useCallback的用法与useState的用法基本一致,但最后会返回一个函数,用一个变量保存起来. 返回的函数a会根据b的变化而变化,如果b始终未发生变化,a也不会重新生成,避免函数在不必要的情况下更新. 记得子组件导出时使用memo包裹一下,其作用是对组件前后两次进行浅对比,阻止不必要的更新

  • React useMemo和useCallback的使用场景

    useMemo 我们知道当父组件发生重新渲染时,其所有(状态.局部变量等)都是新的.一旦子组件依赖于父组件的某一个对象变量,那么无论对象是否发生变化,子组件拿到的都是新的对象,从而使子组件对应的 diff 失效,依旧会重新执行该部分逻辑.在下面的例子中,我们的副作用依赖项中包含了父组件传入的对象参数,每次父组件发生更新时,都会触发数据请求. function Info({ style, }) { console.log('Info 发生渲染'); useEffect(() => { consol

  • react组件memo useMemo useCallback使用区别示例

    目录 正文 memo使用 useMemo使用 useCallback使用 正文 memo用来优化函数组件的重复渲染行为,针对的是一个组件 useMemo返回一个memoized的值 本质都是用同样的算法来判定依赖是否发生改变,继而决定是否触发memo或者useMemo中的逻辑,利用memo就可以避免不必要的重复计算,减少资源浪费 useCallback返回一个memoized的函数 useMemo和useCallback都接收两个参数,第一个参数为fn,第二个参数为[],数组中是变化依赖的参数

  • react性能优化useMemo与useCallback使用对比详解

    目录 引言 对比 useMemo useCallback 引言 在介绍一下这两个hooks的作用之前,我们先来回顾一下react中的性能优化.在hooks诞生之前,如果组件包含内部state,我们都是基于class的形式来创建组件.当时我们也知道,react中,性能的优化点在于: 调用setState,就会触发组件的重新渲染,无论前后的state是否不同 父组件更新,子组件也会自动的更新 基于上面的两点,我们通常的解决方案是:使用immutable进行比较,在不相等的时候调用setState:在

  • React中useLayoutEffect钩子使用场景详解

    目录 简介 useEffect钩子的概述 钩子流程 useLayoutEffect钩子的概述 钩子流程 什么时候使用useLayoutEffect钩子? 总结 简介 不久前,React对其功能组件进行了一次重大更新(在2019年3月的16.8版本中),终于为这些组件提供了一种变得有状态的方法. 钩子的加入不仅意味着功能组件将能够提供自己的状态,而且还能通过引入useEffect钩子来管理自己的生命周期事件. 此外,这次更新还引入了一个全新的useLayoutEffect钩子,根据React文档,

  • React 中 setState 的异步操作案例详解

    目录 前言 React 中的 setState 为什么需要异步操作? 什么时候setState会进行同步操作? 前言 在使用state的时候, 如果我们企图直接修改state中的某一个值之后直接打印(使用)他,就会发现,他其实并没有改变. 就像下面的例子,企图通过点击事件之后就使用修改之后的state的值,但是会发state中的并没有被立即修改,还是原先的值,我们都知道那是因为 setState就相当于是一个异步操作,不能立即被修改. import React, { Component } fr

  • react中的ajax封装实例详解

    react中的ajax封装实例详解 代码块 **opts: {'可选参数'} **method: 请求方式:GET/POST,默认值:'GET'; **url: 发送请求的地址, 默认值: 当前页地址; **data: string,json; **async: 是否异步:true/false,默认值:true; **cache: 是否缓存:true/false,默认值:true; **contentType: HTTP头信息,默认值:'application/x-www-form-urlenc

  • Vue2.x与Vue3.x中路由钩子的区别详解

    目录 vue2.x 前置概念: 路由钩子分类 路由和组件的概念(方便理解钩子函数) 全局路由钩子 路由配置守卫钩子 组件内的守卫钩子 路由钩子执行顺序 eg: 从A组件跳转到B组件顺序 如果B路有更新, 每次都会执行以下三个钩子: vue3.x 对比变化图 区别补充: vue2.x 前置概念: 路由钩子分类 一共分3类, 7个钩子 路由和组件的概念(方便理解钩子函数) 路由和组件是2个概念, 可以粗犷的认为: 路由是浏览器网址 组件是显示在网页上的不同内容 全局路由钩子 router.befor

  • React中使用Vditor自定义图片详解

    安装 npm install vditor -s 引用 导入依赖包 import Vditor from "vditor"; 导入样式 import "vditor/src/assets/scss/index.scss"; 使用示例 export default class Vditor extends Component { constructor(props) { super(props); this.state = { editValue: "&qu

  • React中如何引入Angular组件详解

    前言 为了在我的编辑器中使用 Angular,我用 Angular 编写了一个重命名功能.而为了使用它,我得再次使用一次 customEvent ,而在这个微前端架构的系统中,其事件通讯机制已经相当的复杂.在这部分的代码进一步恶化之前,我得尝试有没有别的方式.于是,我想到了之前在其它组件中使用的 Web Components 技术,而 Angular 6 正好可以支持. 下面话不多说了,来一起看看详细的介绍吧 HTML 中引入 Web Components 我所需要做的事情也相当的简单,只需要将

  • React中Ref 的使用方法详解

    本文实例讲述了React中Ref 的使用方法.分享给大家供大家参考,具体如下: React中Ref 的使用 React v16.6.3 在典型的React数据流中,props是父组件与其子组件交互的唯一方式.要修改子项,请使用new props 重新呈现它.但是,在某些情况下,需要在典型数据流之外强制修改子项.要修改的子项可以是React组件的实例,也可以是DOM元素.对于这两种情况,React都提供了api. 何时使用refs refs有一些很好的用例: 1.文本选择或媒体播放. 2.触发势在

  • sass在react中的基本使用(实例详解)

    目录 1. 安装sass 2. 编写App.tsx中的基本DOM 3. sass变量 4. sass中的选择器嵌套和属性嵌套 5. sass中的@import和Partials 6. Sass中的 @mixin 与 @include 7.sass中的继承 @extend 8. 源代码 1. 安装sass 较新的版本不需要配置sass-loader等一系列插件,安装即用. npm install --save-dev sass 2. 编写App.tsx中的基本DOM 更改app.css为app.s

  • react中JSX的注意点详解

    目录 1JSX是一个表达式 2JSX的属性 2.1驼峰命名 2.2style接收一个对象 3JSX标签没有子元素 4JSX防止注入攻击 5唯一父元素 总结 1 JSX 是一个表达式 JSX 是 JavaScript 的语法扩展,本质上是 React.createElement()方法的语法糖. Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,所以它被看作一个表达式. 这意味着你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋

  • vue中filter的应用场景详解

    filter一般用于过滤某些值,比如我这个字段是空,可是我想在前端显示"–",就可以使用到它了. 最近碰到一个需求就是要给某些字段可以设置权限去以其他形式显示,比如以"***"显示需要隐藏的金额. 1.获取金额权限 2.通过filter过滤满足条件的字段 3.返回隐藏的样式 看代码: //其他的看,看我标注的就可以了 //scope.row 获取当前行 <template slot-scope="scope"> <templat

随机推荐