人在身处逆境时,适应环境的能力实在惊人。人可以忍受不幸,也可以战胜不幸,因为人有着惊人的潜力,只要立志发挥它,就一定能渡过难关。

Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 组件的情况下使用 state 以及其他的 React 特性。

React Hooks 表现形式是以 use 开头的函数被称为 HookuseState 是 React 提供的一个内置 Hook。你可以在 React API 参考 中找到其他内置的 Hook。你也可以通过组合现有的 Hook 来编写属于你自己的 Hook。

跟普通函数相比,Hook 比普通函数更为严格。你只能在你的组件(或其他 Hook)的顶层调用 Hook。如果你想在一个条件或循环中使用 useState,请提取一个新的组件并在组件内部使用它。

为什么要使用 Hooks?

  • 解决高阶类组件复用,导致代码层级复杂问题。
  • React 组件生命周期的复杂,用于代替生命周期函数。
  • 如果一个类一开始设计成了 function 组件,无状态组件,因为需要状态,又改成了 class 成本高。

1. State Hook

State 让组件“记住”用户输入之类的信息。例如,表单组件可以使用 state 来存储输入值,而图片库组件可以使用 state 来存储所选的图像索引。要给组件添加状态,可以使用以下介绍的钩子之一。

1.1 useState

useState 是一个 React Hook。它允许你向组件添加一个状态变量。模拟类组件的状态管理。

  1. // usss
  2. const [state, setstate] = usestate(initialState)

1.2 useReducer

useReducer 是一个 React Hook,它允许你向组件里面添加一个 reducer,来维护一个状态 state。useReducer 不支持异步处理,异步处理需要借助于 Hooks useEffect。

在单个组件中实现状态管理,理解 useReducer 的使用。

  1. const [state, dispatch] = useReducer(reducer, initialState)

其次配合 useContext 跨级通信。将数据逻辑(即状态管理)从组件中(视图逻辑)分离出来通过外部管理,降低组件耦合度。对于单个组件来说意义不大,但是对于多个组件数据需要共享状态的时候很方便。

2. Context Hook

2.1 useContext

useContext 是一个 React Hook,可以让你读取和订阅组件中的 context。减少组件层级,便于组件跨级通信处理。

useContext 配合 useState、useContext 配合 useReducer。

3. Ref Hooks

Refs 允许组件保存一些不用于呈现(渲染)的信息,比如 DOM 节点或超时 ID。与 state 不同,更新 ref 并不会重新呈现组件。React 提供了 useRef hook 来描述。

3.1 useRef

保存引用值:

  1. const ref = useRef(initialValue)

4. Effect Hooks

Effect 允许组件 连接到外部系统并与之同步。这包括处理网络、浏览器、DOM、动画、使用不同 UI 库编写的 widgets 以及其他非 React 代码。

Effect Hooks 副作用钩子函数很好模拟了类组件的生命周期函数。但是我们知道 Function Component 不存在生命周期,所以不要把 Class Component 的生命周期概念搬过夹试图对号入座。

4.1 useEffect

useEffect 是一个 React Hook,它允许你 连接到外部系统并与之同步

  1. useEffect(setup, dependencies?)
  2. // 处理副作用
  3. useEffect(() => {
  4. // 副作用函数处理代码块 { 比如数据请求,定时器 }
  5. console.log("effect")
  6. return () => {
  7. console.log("cleanup")
  8. // cleanup
  9. // 执行时机:无依赖情况下:组件销毁执行 有依赖情况下:依赖更新和组件销毁的时候
  10. }
  11. }, [ name /* 依赖的状态,如果为空表示不依赖任何状态 */])

依赖:不要对 Dependencies 撒谎,如果你明明在 effect 中使用了某个变量,却没有申明在依赖中,你等于向 React 撒了谎,后果就是,当依赖的变量改变时,useEffect 也不会再次执行,eslint 会报警告。

4.2 useLayoutEffect

useLayoutEffectuseEffect 的一个版本,在浏览器重新绘制屏幕之前触发。useLayoutEffect 内部的代码和所有计划的状态更新阻塞了浏览器重新绘制屏幕。如果过度使用,这会使你的应用程序变慢。如果可能的话,尽量选择 useEffect

然后如果 Effect 一定要阻止浏览器绘制屏幕,使用 useLayoutEffect 替换 useEffect。请注意,绝大多数的 Effect 都不需要这样。只有当在浏览器绘制之前运行 Effect 非常重要的时候才需要如此:例如,在用户看到 tooltip 之前测量并定位它。

4.3 useInsertionEffect

useInsertionEffect 是为 CSS-in-JS 库的作者特意打造的。除非你正在使用 CSS-in-JS 库并且需要注入样式,否则你应该使用 useEffect 或者 useLayoutEffect

4.4 Effect Hooks 之间区别

简单来说就是调用时机不同,useLayoutEFfect 和原来 componentDidMount & componentDidUpdate 一致,在 React 完成 Dom 更新后马上同步调用的代码,即在浏览器重新绘制屏幕之前触发 useLayouteEffect。你可以在这里测量布局。会阻塞页面渲染(渲染树)。

useEffect 是会在整个页面渲染完才会调用的代码。

useInsertionEffect 会在 React 修改 DOM 之前触发。可以在这里插入动态 CSS。

官方建议优先使用 useEffect

However, we recommend starting with useEffect first and only trying useLayoutEffect if that causes a problem.

在实际使用时如果想避免页面抖动(即在 useEffect 里修改 Dom 很有可能出现)的话,可以把需要操作 Dom 的代码放在 useLayoutEffect 里。在这里做点 Dom 操作,这些 Dom 修改会和 react 做出的更改一起被一次性渲染到屏幕上,只有一次回流、重绘的代价。

5. 性能 Hook

5.1 useMemo

useMemo 是一个 React Hook,它在每次重新渲染的时候能够缓存、使用计算的结果。

  1. const cachedValue = useMemo(calculateValue, dependencies)
  2. useMemo(() => first, [second])

记忆纯函数计算结果、跳过组件的重新渲染,记忆一个函数。

对于使用 useMemo 记忆一个函数,这看起来很笨拙!记忆函数很常见,React 有一个专门用于此的内置 Hook。将你的函数包装到 useCallback 而不是 useMemo 中,以避免编写额外的嵌套函数。 即 useCallback 的唯一好处是它可以让你避免在内部编写额外的嵌套函数。它没有做任何其他事情。

5.2 useCallBack

useCallback 是一个允许你在多次渲染中缓存函数的 React Hook。记忆函数,防止因为组件重新渲染,导致组件内部定义的方法被重新创建,起到缓存作用。只有第二个参数依赖项变化了才重新声明一次。如果依赖传入空数组,那么函数第一次创建后就被缓存,这时如果函数定义中的使用了某个状态值改变了,以后调用函数拿到的还是老的值。如果不传第二个参数,每次都会重新声明一次。

  1. const cachedFn = useCallback(fn, dependencies)

和 useMemo 唯一的区别是:useCallback 不会执行第一个参数函数,而是将它返回给你,而 useMemo 会执行第一个参数函数并且将函数执行结果返回给你。所以在前面的例子中,可以返回 handleClick 来达到存储函数的目的。

所以 useCallback 常用记忆事件函数,生成记忆后的事件函数并传递给子组件使用。而 useMemo 更适合经过函数计算得到一个确定的值,比如记忆组件、结果。

5.3 useTransition

useTransition 允许将状态转换标记为非阻塞,并允许其他更新中断它此更新。

5.4 useDeferredValued

useDeferredValue 是一个 React Hook,可以让你延迟更新 UI 的某些部分。

6. 资源 Hook

use 是一个 React Hook,它可以让你读取类似于 Promisecontext 的资源的值。

7. 其他 Hook

这些 Hook 主要对库作者有用,而不常用于应用程序代码。

useDebugValue 允许在 React 开发者工具中为自定义 Hook 添加一个标签。

useId 允许组件绑定一个唯一 ID,其通常与可访问性 API 一起使用。

useSyncExternalStore 允许一个组件订阅一个外部 store。

8. 自定义 Hooks

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。即抽离复用 js 逻辑,让结构更加清晰,符合函数式编程思想。

必须以 'use' 开头吗?必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含对其内部 Hook 的调用,React 将无法自动检查你的 Hook 是否违反了 Hook 的规则。官网主要研究以下几个问题:

  • 什么是自定义钩子,如何编写自己的钩子;
  • 如何命名和结构化自定义的钩子;
  • 何时以及为什么要提取自定义钩子;
  • 如何在组件之间重用逻辑;

React Hooks 钩子特性的更多相关文章

  1. React Hooks新特性学习随笔

    React Hooks 是 React 16.8 的新增特性.它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性. 前言 本篇主要以讲几个常用的api为主. 1.u ...

  2. 使用React Hooks新特性useReducer、useContext替代传统Redux高阶组件案例

    当我们使用redux进行数据管理的时候,一般都是在根组件通过Provider的方式引入store,然后在每个子组件中,通过connect的方式使用高阶组件进行连接,这样造成的一个问题是,大量的高阶组件 ...

  3. React Hooks用法大全

    前言 在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我们依赖 ...

  4. react新特性 react hooks

    本文介绍的是react新特性react hooks,本文面向的是有一定react开发经验的小伙伴,如果你对react还不是很熟悉的话我建议你先学习react并多多联系. 首先我们都知道react有3种 ...

  5. 30分钟精通React今年最劲爆的新特性——React Hooks

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周 ...

  6. 关于React Hooks,你不得不知的事

    React Hooks是React 16.8发布以来最吸引人的特性之一.在开始介绍React Hooks之前,让咱们先来理解一下什么是hooks.wikipedia是这样给hook下定义的: In c ...

  7. 如何构建自己的 react hooks

    我们组的前端妹子在组内分享时谈到了 react 的钩子,趁此机会我也对我所理解的内容进行下总结,方便更多的同学了解.在 React 的 v16.8.0 版本里添加了 hooks 的这种新的 API,我 ...

  8. React Hooks究竟是什么呢?

    摘要: React Hooks原理解析. 原文:快速了解 React Hooks 原理 译者:前端小智 我们大部分 React 类组件可以保存状态,而函数组件不能? 并且类组件具有生命周期,而函数组件 ...

  9. React Hooks简单业务场景实战(非源码解读)

    前言 React Hooks 是React 16.7.0-alpha 版本推出的新特性.从 16.8.0 开始,React更稳定的支持了这一新特性. 它可以让你在不编写 class 的情况下使用 st ...

  10. React hooks详解

    此篇文章仅是对hooks入门的总结,老鸟略过吧~ React从16.8.X以后增加了一个新特性,react hooks 让我们看看这个新特性又带来了哪些惊喜呢~以下内容我们采取不同方式创建组件来进行对 ...

随机推荐

  1. KVM下windows由IDE模式改为virtio模式蓝屏 开不开机

    KVM安装Windows默认使用的是qemu虚拟化IDE硬盘模式,在这种情况下,IO性能比较低,如果使用virtio的方式可以提高虚拟机IO性能. 于是我想将这台虚拟机迁移到openstack中管理 ...

  2. 谈谈JSF业务线程池的大小配置

    1.简介 JSF业务线程池使用JDK的线程池技术,缺省情况下采用Cached模式(核心线程数20,最大线程数200).此外,还提供了Fixed固定线程大小的模式,两种模式均可设置请求队列大小. 本文旨 ...

  3. k8s 自动扩缩容HPA原理及adapter配置详解👑

    大家好,我是蓝胖子,都知道,k8s拥有自动扩缩容机制HPA,我们能够通过配置针对不同的扩缩容场景进行自动扩缩容,往往初学者在面对其中繁多配置的时候会学了又忘记,今天我将会以一种不同的视角,结合api ...

  4. Dubbo3应用开发—Dubbo服务管理平台DubboAdmin介绍、安装、测试

    Dubbo服务管理平台 DubboAdmin的介绍 Dubbo Admin是Apache Dubbo服务治理和管理系统的一部分. Dubbo Admin提供了一套用于服务治理的Web界面,让我们可以更 ...

  5. RPM软件包:Red HatPackage Manager,RPM

    RPM软件包是按照GPL条款发行在各个linux版本上使用. 用途 可以安装.删除.升级.刷新和管理RPM软件包 通过RPM软件包管理能知道软件包包含哪些文件,也能知道系统中的某个文件属于哪个RPM软 ...

  6. DPDK丢包那些事

    本文来自博客园,作者:T-BARBARIANS,博文严禁转载,转载必究! 一.前言 DPDK技术原理相关的文章不胜枚举,但从实战出发,针对DPDK丢包这一类问题进行系统分析的文章还是凤毛麟角. 刚好最 ...

  7. unity利用Rigibody实现第一人称移动

    1. CameraRotation脚本,将它给MainCamera,实现上下视角旋转 using System.Collections; using System.Collections.Generi ...

  8. mysql出现10061错误解决方法

    首先要关闭MYSQL服务 关闭你现在正在运行的mysql数据库,用结束mysql进程或者直接关闭mysql服务器都可以 1.开始菜单->运行(cmd)->寻径到MySQL文件中的bin目录 ...

  9. ES6入门(一)

    1.let声明的变量只在let命令所在的代码块内有效 2.不存在变量提升,先使用变量,后定义变量,就会报错. 3.let不允许在相同作用域内,重复声明同一个变量.

  10. mysqli操作

    1.使用mysqli_connect()函数,语法如下: mysqli 对象名=mysqli_connect(数据库服务名,用户名,密码,数据库名) 例:$conn=mysqli_connect('l ...