React 小技巧教你如何摆脱hooks依赖烦恼

react项目中,很常见的一个场景:

const [watchValue, setWatchValue] = useState('');
const [otherValue1, setOtherValue1] = useState('');
const [otherValue2, setOtherValue2] = useState('');

useEffect(() => {
    doSomething(otherValue1, otherValue2);
}, [watchValue, otherValue1, otherValue2]);

我们想要watchValue改变的时候执行doSomething,里面会引用其他值otherValue1, otherValue2

这时有个让人烦恼的问题:

  • 如果不把otherValue1, otherValue2加入依赖数组的话,doSomething里面很可能会访问到otherValue1, otherValue2旧的变量引用,从而发生意想不到的错误(如果安装hooks相关eslint的话,会提示警告)。
  • 反之,如果把otherValue1, otherValue2加入依赖数组的话,这两个值改变的时候doSomething也会执行,这并不是我们想要的(我们只想引用他们的值,但不想它们触发doSomething)。

otherValue1, otherValue2变成ref可以解决这个问题:

const [watchValue, setWatchValue] = useState('');
const other1 = useRef('');
const other2 = useRef('');

// ref可以不加入依赖数组,因为引用不变
useEffect(() => {
    doSomething(other1.current, other2.current);
}, [watchValue]);

这样other1, other2的变量引用不会变,解决了前面的问题,但是又引入了一个新的问题:other1, other2的值current改变的时候,不会触发组件重新渲染(useRef的current值改变不会触发组件渲染),从而值改变时候界面不会更新!

这就是hooks里面的一个头疼的地方,useState变量会触发重新渲染、保持界面更新,但作为useEffect的依赖时,又总会触发不想要的函数执行。useRef变量可以放心作为useEffect依赖,但是又不会触发组件渲染,界面不更新。
如何解决?

可以将useRefuseState的特性结合起来,构造一个新的hooks函数: useStateRef

import { useState, useRef } from "react";

// 使用 useRef 的引用特质, 同时保持 useState 的响应性
type StateRefObj<T> = {
  _state: T;
  value: T;
};
export default function useStateRef<T>(
  initialState: T | (() => T)
): StateRefObj<T> {
  // 初始化值
  const [init] = useState(() => {
    if (typeof initialState === "function") {
      return (initialState as () => T)();
    }
    return initialState;
  });
  // 设置一个 state,用来触发组件渲染
  const [, setState] = useState(init);

  // 读取value时,取到的是最新的值
  // 设置value时,会触发setState,组件渲染
  const [ref] = useState<StateRefObj<T>>(() => {
    return {
      _state: init,
      set value(v: T) {
        this._state = v;
        setState(v);
      },
      get value() {
        return this._state;
      },
    };
  });

  // 返回的是一个引用变量,整个组件生命周期之间不变
  return ref;
}

这样,我们就能这样用:

const watch = useStateRef('');
const other1 = useStateRef('');
const other2 = useStateRef('');

// 这样改变值:watch.value = "new";

useEffect(() => {
    doSomething(other1.value, other2.value);
   // 其实现在这三个值都是引用变量,整个组件生命周期之间不变,完全可以不用加入依赖数组
   // 但是react hooks的eslint插件只能识别useRef作为引用,不加人会警告,为了变量引用安全还是加入
}, [watch.value, other1, other2]);

这样,watch, other1,other2useRef的引用特性,不会触发doSomething不必要的执行。又有了useState的响应特性,改变.value的时候会触发组件渲染和界面更新。
我们想要变量改变触发doSomething的时候,就把watch.value加入依赖数组。我们只想引用值而不想其触发doSomething的时候,就把变量本身加入数组。

以上就是React 小技巧教你如何摆脱hooks依赖烦恼的详细内容,更多关于React hooks依赖的资料请关注我们其它相关文章!

(0)

相关推荐

  • 如何对react hooks进行单元测试的方法

    写在前面 使用 react hook 来做公司的新项目有一段时间了,大大小小的坑踩了不少.由于是公司项目,因此必须要编写单元测试来确保业务逻辑的正确性以及重构时代码的可维护性与稳定性,之前的项目使用的是 react@15.x 的版本,使用 enzyme 配合 jest 来做单元测试毫无压力,但新项目使用的是 react@16.8 ,编写单元测试的时候,遇到不少阻碍,因此总结此篇文章算作心得分享出来. 配合 enzyme 来进行测试 首先,enzyme 对于 hook 的支持程度,可以参考这个 i

  • React Hooks 实现和由来以及解决的问题详解

    与React类组件相比,React函数式组件究竟有何不同? 一般的回答都是: 类组件比函数式组件多了更多的特性,比如 state,那如果有 Hooks 之后呢? 函数组件性能比类组件好,但是在现代浏览器中,闭包和类的原始性能只有在极端场景下才会有明显的差别. 性能主要取决于代码的作用,而不是选择函数式还是类组件.尽管优化策略有差别,但性能差异可以忽略不计. 参考官网:(https://zh-hans.reactjs.org/docs/hooks-faq.html#are-hooks-slow-b

  • React Hooks的深入理解与使用

    你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? --拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function. 你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? --拥有了Hooks,生命周期钩子函数可以先丢一边了. 你在还在为组件中的this指向而晕头转向吗? --既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this. 这样看来,说React Hooks是今年最劲爆的新特性真的毫不夸张.如果你也对react

  • 记录一次完整的react hooks实践

    写在前面 React在16.8版本正式发布了Hooks.关注了很久,最近正好有一个小需求,赶紧来试一下. 需求描述 需求很简单,部门内部的一个数据查询小工具.大致长成下面这样: 用户首次访问页面,会拉取数据展示.输入筛选条件,点击查询后,会再次拉取数据在前端展示. 需求实现 使用React Class Component的写法 如果使用以前的class写法,简单写一下,代码可能大概长成下面这样: import React from 'react'; import { Tabs, Input, R

  • 详解如何使用React Hooks请求数据并渲染

    前言 在日常的开发中,从服务器端异步获取数据并渲染是相当高频的操作.在以往使用React Class组件的时候,这种操作我们已经很熟悉了,即在Class组件的componentDidMount中通过ajax来获取数据并setState,触发组件更新. 随着Hook的到来,我们可以在一些场景中使用Hook的写法来替代Class的写法.但是Hook中没有setState.componentDidMount等函数,又如何做到从服务器端异步获取数据并渲染呢?本文将会介绍如何使用React的新特性Hook

  • React 使用Hooks简化受控组件的状态绑定

    开始之前 阅读本文需要对以下几项有一定了解 ECMAScript 6 文章中大量用到了 ES6 语法,比如解构赋值和函数参数默认值.剩余参数.展开语法.箭头函数等. Hooks React 在 16.8 版本中推出了 Hooks,它允许你在"函数组件"中使用"类组件"的一些特性. React 本身提供了一些 Hooks,比如 useState.useReducer 等.通过在一个以"use"作为命名起始的函数中调用这些 Hooks,就得到了一个

  • React 小技巧教你如何摆脱hooks依赖烦恼

    react项目中,很常见的一个场景: const [watchValue, setWatchValue] = useState(''); const [otherValue1, setOtherValue1] = useState(''); const [otherValue2, setOtherValue2] = useState(''); useEffect(() => { doSomething(otherValue1, otherValue2); }, [watchValue, othe

  • PHP 开发者该知道的 5 个 Composer 小技巧

    Composer 是新一代的PHP依赖管理工具.其介绍和基本用法可以看这篇<Composer PHP依赖管理的新时代>.本文介绍使用Composer的五个小技巧,希望能给你的PHP开发带来方便. 1. 仅更新单个库 只想更新某个特定的库,不想更新它的所有依赖,很简单: composer update foo/bar 此外,这个技巧还可以用来解决"警告信息问题".你一定见过这样的警告信息: Warning: The lock file is not up to date wi

  • 编写简洁React组件的小技巧

    本文源于翻译文章 Simple tips for writing clean React components, 原文作者 Iskander Samatov 在这篇文章中,我们会回顾一些简单的技巧,它们将帮助我们编写更简洁的 React 组件,并且更好地扩展我们的项目. 避免使用扩展操作符传递 props 首先,让我们从一个应该避免的反模式开始.除非有明确的理由这样做,否则应该避免在组件树中使用扩展操作符传递props,比如:{ ...props }. 通过这种方式传递 props 确实可以更快

  • 详解React Native顶|底部导航使用小技巧

    导航一直是App开发中比较重要的一个组件,ReactNative提供了两种导航组件供我们使用,分别是:NavigatorIOS和Navigator,但是前者只能用于iOS平台,后者在ReactNative0.44版本以后已经被移除了. 好在有人提供了更好的导航组件,就是我们今天要讲的react-navigation,并且ReactNative官方更推荐我们使用此组件. 本篇文章只讲解基础用法,如果你想了解更多,请戳这里->戳我.  简介 react-navigation主要包括导航,底部tab,

  • 关于TypeScript开发的6六个实用小技巧分享

    目录 1. 开发之前确定实体类型 2. 请求接口时只需要定义自己需要用到的字段 3. 使用枚举类型 4. DOM元素的类型要正常给 5.对象的类型要怎么给 6.结构赋值时类型怎么给 总结 本文总结一下使用TypeScript开发应用程序的一点小经验.说之前,推荐一个VSCODE立即执行TS代码的插件quokka.js, 使用方式,ctrl+shipt+p,输入关键字quokka 回车之后,输入代码之后会立即执行 1. 开发之前确定实体类型 在正式编码之前,如果没有接口文档的话,最好能拿到数据字典

  • 改变cmd命令提示符颜色的3个小技巧

    从Windows 95到现在的Windows 8,系统中带的DOS命令提示符软件都是黑白画面,在这个五光十色的年代,这样的软件实在有点让人感觉没有新鲜感,下面教大家几个自定义DOS命令提示符颜色的小技巧. 第一个技巧是教大家改变DOS命令提示符的标题,在开始菜单点运行,输入"CMD /k TITLE标题文字"可以得到自定义标题效果 第二个技巧可以改变命令符:在开始菜单点运行,输入"CMD /K PROMPT [text]"(text为新的命令提示符), 第三个技巧可

  • 11个教程中不常被提及的JavaScript小技巧(推荐)

    1.过滤唯一值 Set类型是在ES6中新增的,它类似于数组,但是成员的值都是唯一的,没有重复的值.结合扩展运算符(...)我们可以创建一个新的数组,达到过滤原数组重复值的功能. const array = [1, 2, 3, 3, 5, 5, 1]; const uniqueArray = [...new Set(array)]; console.log(uniqueArray); // [1, 2, 3, 5] 在ES6之前,我们如果想要实现这个功能的话,需要的处理代码要多很多. 这个技巧的适

  • JavaScript小技巧带你提升你的代码技能

    目录 1.过滤唯一值 2.短路求值(Short-Circuit Evaluation) 2.1场景举例 3.转换Boolean型 4.转换String型 5.转换Number类型 6.快速求幂 7.快速Float转Integer 7.1使用场景 8.类中自动绑定 9.截取数组 10.获取数组中的最后的元素 11.格式化JSON代码 今天,我将跟大家分享11个在日常教程中不常被提及的JavaScript小技巧,他们往往在我们的日常工作中经常出现,但是又很容易被忽略. 1.过滤唯一值 Set类型是在

  • 学习JavaScript一定要知道的3个小技巧

    目录 一.神奇的扩展运算符 1.拷贝数组 2.合并数组 3.展开对象 二.进行空检查的最佳方法 1.可选链操作符 2.空值合并运算符 三.使用 .map()..reduce() 和 .filter() 前言: 通常在 Angular 或 React 项目中,code review 时看到一些老式的 JavaScript 代码,就会将开发人员归类为初学者.但是,如果您知道以下 3 个技巧,您将被视为现代 JavaScript 的尤达大师.那么,让我们开始我们的旅程吧! 一.神奇的扩展运算符 扩展运

  • JavaScript的11个小技巧整理

    目录 1.过滤唯一值 2.短路求值(Short-Circuit Evaluation) 工作原理 场景举例 3.转换Boolean型 4.转换String型 5.转换Number类型 6.快速求幂 7.快速Float转Integer 使用场景 8.类中自动绑定 9.截取数组 10.获取数组中的最后的元素 11.格式化JSON代码 1.过滤唯一值 Set类型是在ES6中新增的,它类似于数组,但是成员的值都是唯一的,没有重复的值.结合扩展运算符(...)我们可以创建一个新的数组,达到过滤原数组重复值

随机推荐