一、是什么

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

至于为什么引入hook,官方给出的动机是解决长时间使用和维护react过程中常遇到的问题,例如:

  • 难以重用和共享组件中的与状态相关的逻辑
  • 逻辑复杂的组件难以开发与维护,当我们的组件需要处理多个互不相关的 local state 时,每个生命周期函数中可能会包含着各种互不相关的逻辑在里面
  • 类组件中的this增加学习成本,类组件在基于现有工具的优化上存在些许问题
  • 由于业务变动,函数组件不得不改为类组件等等

在以前,函数组件也被称为无状态的组件,只负责渲染的一些工作

因此,现在的函数组件也可以是有状态的组件,内部也可以维护自身的状态以及做一些逻辑方面的处理

二、有哪些

上面讲到,Hooks让我们的函数组件拥有了类组件的特性,例如组件内的状态、生命周期

最常见的hooks有如下:

  • useState
  • useEffect
  • 其他

useState

首先给出一个例子,如下:

  1. import React, { useState } from 'react';
  2.  
  3. function Example() {
  4. // 声明一个叫 "count" 的 state 变量
  5. const [count, setCount] = useState(0);
  6.  
  7. return (
  8. <div>
  9. <p>You clicked {count} times</p>
  10. <button onClick={() => setCount(count + 1)}>
  11. Click me
  12. </button>
  13. </div>
  14. );
  15. }

在函数组件中通过useState实现函数内部维护state,参数为state默认的值,返回值是一个数组,第一个值为当前的state,第二个值为更新state的函数

该函数组件等价于的类组件如下:

  1. class Example extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. count: 0
  6. };
  7. }
  8.  
  9. render() {
  10. return (
  11. <div>
  12. <p>You clicked {this.state.count} times</p>
  13. <button onClick={() => this.setState({ count: this.state.count + 1 })}>
  14. Click me
  15. </button>
  16. </div>
  17. );
  18. }
  19. }

从上述两种代码分析,可以看出两者区别:

  • state声明方式:在函数组件中通过 useState 直接获取,类组件通过constructor 构造函数中设置

  • state读取方式:在函数组件中直接使用变量,类组件通过this.state.count的方式获取

  • state更新方式:在函数组件中通过 setCount 更新,类组件通过this.setState()

总的来讲,useState 使用起来更为简洁,减少了this指向不明确的情况

useEffect

useEffect可以让我们在函数组件中进行一些带有副作用的操作

同样给出一个计时器示例:

  1. class Example extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. count: 0
  6. };
  7. }
  8.  
  9. componentDidMount() {
  10. document.title = `You clicked ${this.state.count} times`;
  11. }
  12. componentDidUpdate() {
  13. document.title = `You clicked ${this.state.count} times`;
  14. }
  15.  
  16. render() {
  17. return (
  18. <div>
  19. <p>You clicked {this.state.count} times</p>
  20. <button onClick={() => this.setState({ count: this.state.count + 1 })}>
  21. Click me
  22. </button>
  23. </div>
  24. );
  25. }
  26. }

从上面可以看见,组件在加载和更新阶段都执行同样操作

而如果使用useEffect后,则能够将相同的逻辑抽离出来,这是类组件不具备的方法

对应的useEffect示例如下:

  1. import React, { useState, useEffect } from 'react';
  2. function Example() {
  3. const [count, setCount] = useState(0);
  4.  
  5. useEffect(() => { document.title = `You clicked ${count} times`; });
  6. return (
  7. <div>
  8. <p>You clicked {count} times</p>
  9. <button onClick={() => setCount(count + 1)}>
  10. Click me
  11. </button>
  12. </div>
  13. );
  14. }

useEffect第一个参数接受一个回调函数,默认情况下,useEffect会在第一次渲染和更新之后都会执行,相当于在componentDidMountcomponentDidUpdate两个生命周期函数中执行回调

如果某些特定值在两次重渲染之间没有发生变化,你可以跳过对 effect 的调用,这时候只需要传入第二个参数,如下:

  1. useEffect(() => {
  2. document.title = `You clicked ${count} times`;
  3. }, [count]); // 仅在 count 更改时更新

上述传入第二个参数后,如果 count 的值是 5,而且我们的组件重渲染的时候 count 还是等于 5,React 将对前一次渲染的 [5] 和后一次渲染的 [5] 进行比较,如果是相等则跳过effects执行

回调函数中可以返回一个清除函数,这是effect可选的清除机制,相当于类组件中componentwillUnmount生命周期函数,可做一些清除副作用的操作,如下:

  1. useEffect(() => {
  2. function handleStatusChange(status) {
  3. setIsOnline(status.isOnline);
  4. }
  5.  
  6. ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  7. return () => {
  8. ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  9. };
  10. });

所以, useEffect相当于componentDidMountcomponentDidUpdate 和 componentWillUnmount 这三个生命周期函数的组合

其它 hooks

在组件通信过程中可以使用useContextrefs学习中我们也用到了useRef获取DOM结构......

还有很多额外的hooks,如:

  • useReducer
  • useCallback
  • useMemo
  • useRef

三、解决什么

通过对上面的初步认识,可以看到hooks能够更容易解决状态相关的重用的问题:

  • 每调用useHook一次都会生成一份独立的状态

  • 通过自定义hook能够更好的封装我们的功能

编写hooks为函数式编程,每个功能都包裹在函数中,整体风格更清爽,更优雅

hooks的出现,使函数组件的功能得到了扩充,拥有了类组件相似的功能,在我们日常使用中,使用hooks能够解决大多数问题,并且还拥有代码复用机制,因此优先考虑hooks

React Hooks的理解的更多相关文章

  1. 理解 React Hooks 心智模型:必须按顺序、不能在条件语句中调用的规则

    前言 自从 React 推出 hooks 的 API 后,相信大家对新 API 都很喜欢,但是它对你如何使用它会有一些奇怪的限制.比如,React 官网介绍了 Hooks 的这样一个限制: 不要在循环 ...

  2. 理解 React Hooks

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由志航发表于云+社区专栏 TL;DR 一句话总结 React Hooks 就是在 react 函数组件中,也可以使用类组件(classe ...

  3. 通过 React Hooks 声明式地使用 setInterval

    本文由云+社区发表 作者:Dan Abramov 接触 React Hooks 一定时间的你,也许会碰到一个神奇的问题: setInterval 用起来没你想的简单. Ryan Florence 在他 ...

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

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

  5. 从Mixin到hooks,谈谈对React16.7.0-alpha中即将引入的hooks的理解

      为了实现分离业务逻辑代码,实现组件内部相关业务逻辑的复用,在React的迭代中针对类组件中的代码复用依次发布了Mixin.HOC.Render props等几个方案.此外,针对函数组件,在Reac ...

  6. react新特性 react hooks

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

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

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

  8. React Hooks 你不来了解下?

    前言 最近在看 React 的新语法-- React Hooks,只能一句话概括:React 语法真的是越来越强大,越写代码越少. 强烈推荐还没看 React Hooks 的同学去学习下,这会让你写r ...

  9. React Hooks用法大全

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

随机推荐

  1. MySQL 为什么使用 B+ 树来作索引?

    什么是索引? 所谓的索引,就是帮助 MySQL 高效获取数据的排好序的数据结构.因此,根据索引的定义,构建索引其实就是数据排序的过程. 平时常见的索引数据结构有: 二叉树 红黑树 哈希表 B Tree ...

  2. django 导出excel react下载 --- 导出并下载

    Dajngo查询数据,查询出来之后生成Excel保存本地 class ExportExcel(APIView): def post(self, request, *args, **kwargs): e ...

  3. ES6 学习笔记之对象的新增方法

    1. Object.is() ES5 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===).它们都有缺点,前者会自动转换数据类型,后者的 NaN 不等于自身,以及 +0 等 ...

  4. Docker入门与进阶(上)

    Docker入门与进阶(上) 作者 刘畅 时间 2020-10-17 目录 1 Docker核心概述与安装 1 1.1 为什么要用容器 1 1.2 docker是什么 1 1.3 docker设计目标 ...

  5. 10、修改windows编码集

    10.1.查看Windows的字符集编码: 1.方法一: (1) 同时按住"windows"徽标键和"r"键,在弹出的"运行"框中输入&qu ...

  6. 案例分享:Qt西门子机床人机界面以及数据看板定制(西门子通讯,mysql数据库,生产信息,参数信息,信息化看板,权限控制,播放器,二维图表,参数调试界面)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118685521 长期持续带来更多项目与技术分享 ...

  7. MySql:Navicat 连接不上虚拟机上的mysql容器

    1.问题显示 通过windows主机navicat连接虚拟的mysql时报如下错误. 2.问题原因 由于navicat版本的问题,出现连接失败的原因:mysql8 之前的版本中加密规则是mysql_n ...

  8. Laravel使用Observer(观察者)

      1.创建observer文件,我这里是要记录仓库库存模块的操作日志,所以执行下面的语句,会在app/Observers下面创建WarehouseInventoryObserver文件. php a ...

  9. 9 shell 退出状态

    退出状态和逻辑运算符的组合 Shell 逻辑运算符 举栗 命令的退出状态(exit statu)是指执行完Linux命令或shell函数后,该命令或函数返回给调用它的程序的一个比较小的整数值.if 语 ...

  10. Java 设置PDF跨页表格重复显示表头行

    在创建表格时,如果表格内容出现跨页显示的时候,默认情况下该表格的表头不会在下一页显示,在阅读体验上不是很好.下面分享一个方法如何在表格跨页是显示表格的表头内容,这里只需要简单使用方法 grid.set ...