前言
Hook 是 React 16.8 的新增特性。它是完全可选的,并且100%向后兼容。它可以让你使用函数组件的方式,运用类组件以及 react 其他的一些特性,比如管理状态、生命周期钩子等。从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。

优点:

1、代码可读性更强,原本同一块功能的代码逻辑被拆分在了不同的生命周期函数中,容易使开发者不利于维护和迭代,通过 React Hooks 可以将功能代码聚合,方便阅读维护。例如,每个生命周期中常常会包含一些不相关的逻辑。一般我们都会在 componentDidMount 和 componentDidUpdate 中获取数据。但是,同一个 componentDidMount 中可能也包含很多其它的逻辑,如设置事件监听,而之后需在 componentWillUnmount 中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
2、组件树层级变浅。在原本的代码中,我们经常使用 HOC/render props 等方式来复用组件的状态,增强功能等,无疑增加了组件树层数及渲染,在 React DevTools 中观察过 React 应用,你会发现由 providers,consumers,高阶组件,render props 等其他抽象层组成的组件会形成“嵌套地狱”。而在 React Hooks 中,这些功能都可以通过强大的自定义的 Hooks 来实现。
3、不用再去考虑 this 的指向问题。在类组件中,你必须去理解 JavaScript 中 this 的工作方式。

缺点:

一、响应式的useEffect

写函数组件时,你不得不改变一些写法习惯。你必须清楚代码中useEffectuseCallback的“依赖项数组”的改变时机。有时候,你的useEffect依赖某个函数的不可变性,这个函数的不可变性又依赖于另一个函数的不可变性,这样便形成了一条依赖链。一旦这条依赖链的某个节点意外地被改变了,你的useEffect就被意外地触发了,如果你的useEffect是幂等的操作,可能带来的是性能层次的问题,如果是非幂等,那就糟糕了。

所以,对比componentDidmountcomponentDidUpdate,useEffect带来的心智负担更大。

二、状态不同步

函数的运行是独立的,每个函数都有一份独立的作用域。函数的变量是保存在运行时的作用域里面,当我们有异步操作的时候,经常会碰到异步回调的变量引用是之前的,也就是旧的(这里也可以理解成闭包)。比如下面的一个例子:

import React, { useState } from "react";

const Counter = () => {
const [counter, setCounter] = useState(0);

const onAlertButtonClick = () => {
setTimeout(() => {
alert("Value: " + counter);
}, 3000);
};

return (
<div>
<p>You clicked {counter} times.</p>
<button onClick={() => setCounter(counter + 1)}>Click me</button>
<button onClick={onAlertButtonClick}>
Show me the value in 3 seconds
</button>
</div>
);
};

export default Counter;

当你点击Show me the value in 3 seconds的后,紧接着点击Click me使得counter的值从0变成1。三秒后,定时器触发,但alert出来的是0(旧值),但我们希望的结果是当前的状态1。

这个问题在class component不会出现,因为class component的属性和方法都存放在一个instance上,调用方式是:this.state.xxxthis.method()。因为每次都是从一个不变的instance上进行取值,所以不存在引用是旧的问题。

其实解决这个hooks的问题也可以参照类的instance。用useRef返回的immutable RefObject(current属性是可变的)来保存state,然后取值方式从counter变成了: counterRef.current。如下:

import React, { useState, useRef, useEffect } from "react";

const Counter = () => {
const [counter, setCounter] = useState(0);
const counterRef = useRef(counter);

const onAlertButtonClick = () => {
setTimeout(() => {
alert("Value: " + counterRef.current);
}, 3000);
};

useEffect(() => {
counterRef.current = counter;
});

return (
<div>
<p>You clicked {counter} times.</p>
<button onClick={() => setCounter(counter + 1)}>Click me</button>
<button onClick={onAlertButtonClick}>
Show me the value in 3 seconds
</button>
</div>
);
};

export default Counter;
结果
我们所期待,alert的是当前的值1。

怎么避免react hooks的常见问题

  1. 不要在useEffect里面写太多的依赖项,划分这些依赖项成多个单一功能的useEffect。其实这点是遵循了软件设计的“单一职责模式”。
  2. 如果你碰到状态不同步的问题,可以考虑下手动传递参数到函数。如:
   // showCount的count来自父级作用域
const [count,setCount] = useState(xxx);
function showCount(){ console.log(count) } // showCount的count来自参数
const [count,setCount] = useState(xxx);
function showCount(c){ console.log(c) }

但这个也只能解决一部分问题,很多时候你不得不使用上述的useRef方案。

3. 重视eslint-plugin-react-hooks插件的警告。

4. 复杂业务的时候,使用Component代替hooks。

谈谈react hooks的优缺点的更多相关文章

  1. 基于react hooks,zarm组件库配置开发h5表单页面

    最近使用React Hooks结合zarm组件库,基于js对象配置方式开发了大量的h5表单页面.大家都知道h5表单功能无非就是表单数据的收集,验证,提交,回显编辑,通常排列方式也是自上向下一行一列的方 ...

  2. 谈谈React Native环境安装中我遇到的坑

    谈谈React Native环境安装 这个坑把我困了好久,真的是接近崩溃的边缘...整理出来分享给大家,希望遇到跟我一样问题的小伙伴能尽快找到答案. 首先,这是在初始化App之后,react-nati ...

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

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

  4. 初探React Hooks & SSR改造

    Hooks React v16.8 发布了 Hooks,其主要是解决跨组件.组件复用的状态管理问题. 在 class 中组件的状态封装在对象中,然后通过单向数据流来组织组件间的状态交互.这种模式下,跨 ...

  5. React hooks实践

    前言 最近要对旧的项目进行重构,统一使用全新的react技术栈.同时,我们也决定尝试使用React hooks来进行开发,但是,由于React hooks崇尚的是使用(也只能使用)function c ...

  6. 理解 React Hooks

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

  7. React Hooks新特性学习随笔

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

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

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

  9. react hooks 全面转换攻略(三) 全局存储解决方案

    针对 react hooks 的新版本解决方案 一.redux维持原方案 若想要无缝使用原来的 redux,和其配套的中间件 promise,thunk,saga 等等的话 可以使用 redux-re ...

随机推荐

  1. cobra-强大的CLI应用程序库

    cobra介绍 Cobra是一个用于创建强大的现代CLI应用程序的库,也是一个用于生成应用程序和命令文件的程序. Cobra用于许多Go项目,如Kubernetes.Hugo和Github CLI等. ...

  2. eclipse输入时自动提示

    当输入一部分代码时,其他的候选代码提示出来,可以提高开发的效率,设置方法如下: 选择Window -> Perferences -> Java -> Editor -> Con ...

  3. MYSQL 悲观锁和乐观锁简单介绍及实现

    1:悲观锁 1.1 特点: 每次查询都会进行锁行,怕"其他人"进行数据的修改. 1.2 实现步骤: 步骤1:开启事务test1,并对id=2的记录进行查询,并加锁,如:   步骤2 ...

  4. 必知必会之 Java

    必知必会之 Java 目录 不定期更新中-- 基础知识 数据计量单位 面向对象三大特性 基础数据类型 注释格式 访问修饰符 运算符 算数运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 三目表达式 ...

  5. EFCodeFirst属性映射约定

    EFCodeFirst属性映射约定 EFCodeFirst 属性映射约定 CodeFirst与数据表之间得映射方式又两种:Data Annotation和Fluent API 默认约定: 表名为类名的 ...

  6. 使用python进行接口自动化测试,批量执行测试用例

    工作中,使用python的requests库进行接口自动化测试是一个比较不错的选择,今天就以某网站的免费接口为例,展示以get请求进行批量执行测试用例.话不多说直接开讲 分析一下接口信息, 请求地址: ...

  7. 理解ASP.NET Core 中的WebSocket

    在本文中,我们将详细介绍RFC 6455 WebSocket规范,并配置一个通用的.NET 5应用程序通过WebSocket连接与SignalR通信. 我们将深入底层的概念,以理解底层发生了什么. 关 ...

  8. python学习之常用数据结构

    前言:数据结构不管在哪门编程语言之中都是非常重要的,因为学校的课程学习到了python,所以今天来聊聊关于python的数据结构使用. 一.列表 list 1.列表基本介绍 列表中的每个元素都可变的, ...

  9. Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神!

    封面:洛小汐 作者:潘潘 2021年,仰望天空,脚踏实地. 这算是春节后首篇 Mybatis 文了~ 跨了个年感觉写了有半个世纪 ... 借着女神节 ヾ(◍°∇°◍)ノ゙ 提前祝男神女神们越靓越富越嗨 ...

  10. Pytorch1.7报错 Output 0 of UnbindBackward is a view and is being modified inplace

    utils里内容改成 if scale_each is True: for idx, _ in enumerate([jj for jj in tensor]): t = tensor[idx] # ...