react之自定义hooks

这篇具有很好参考价值的文章主要介绍了react之自定义hooks。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原文合集地址如下,有需要的朋友可以关注

本文地址

合集地址

任何相对独立、复用性强的逻辑,都可以 extract 为自定义 Hook,自定义 Hook 是一种复用 React 的状态逻辑的函数。
自定义 Hook 的主要特点是:

  • 抽象组件间的状态逻辑,方便复用
  • 让功能组件更纯粹,更易于维护
  • 自定义 Hook 可以调用其他 Hook

为什么要用自定义 Hook?

  1. 提炼能复用的逻辑
    许多组件有相似的状态逻辑,使用自定义 Hook 可以很方便地提取出来复用。
  2. 解决复杂组件的可读性问题
    使用自定义 Hook 将复杂组件拆分为更小的功能独立的函数,有助于提高代码的可读性。
  3. 管理数据更新
    使用独立的 Hook 函数来管理数据请求、处理异步逻辑、数据缓存等,易于维护。
  4. 分离状态逻辑
    自定义 Hook 让函数组件更纯粹,只负责 UI,状态逻辑则交给 Hook。
  5. 调用其他 Hook
    自定义 Hook 本身还可以调用 useState、useEffect 等其他 React Hook。

以下是我总结的一些常用的hooks

1、useUpdateEffect

useUpdateEffect作用

useUpdateEffect 是一个自定义的 React Hook,用于在组件更新时执行副作用操作。它类似于 React 的 useEffect,但是会忽略组件的初始渲染阶段,只在组件更新时执行副作用操作。

在 React 中,useEffect 会在组件的每次渲染(包括初始渲染)完成后执行副作用操作。但有时候我们只想在组件更新时执行某些操作,而不关心初始渲染阶段的操作。这就是 useUpdateEffect 的用途。

以下是一个示例:

import { useEffect, useState } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('useEffect - Component has rendered');
  });

  useUpdateEffect(() => {
    console.log('useUpdateEffect - Component has updated');
  });

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

在上述示例中,当点击 “Increment” 按钮时,count 的值会增加并触发组件的重新渲染。useEffect 会在每次渲染后执行,而 useUpdateEffect 只会在组件更新时执行。

通过使用 useUpdateEffect,你可以在组件更新时执行一些特定的副作用操作,如请求数据、更新状态等,而不需要关心初始渲染阶段的操作。

为什么会需要用到useUpdateEffect

在某些情况下,我们希望在 React 组件更新时执行一些特定的副作用操作,而不在初始渲染阶段执行这些操作。这种情况下,我们可以使用类似于 useUpdateEffect 的自定义 Hook。

以下是一些使用 useUpdateEffect 的常见情况:

  1. 避免初始渲染时执行副作用:有些副作用操作可能只需要在组件更新时执行,例如发送网络请求、更新特定状态等。使用 useUpdateEffect 可以确保这些副作用操作在初始渲染时被跳过,只在组件更新时执行。

  2. 监听特定状态的变化:有时我们只关心特定状态的变化,并希望在状态发生变化时执行相应的操作。通过将状态值作为 useUpdateEffect 的依赖项,可以确保副作用操作只在这些状态发生变化时触发。

  3. 更新外部资源或库:有些第三方库或外部资源可能需要在组件更新时进行更新或重新初始化。使用 useUpdateEffect 可以确保在组件更新时调用相应的函数或方法,以便正确地更新这些外部资源。

通过使用 useUpdateEffect,我们可以更加精确地控制副作用操作的触发时机,避免不必要的重复执行,以及在需要时处理特定的更新逻辑。

需要注意的是,React 自带的 useEffect 可以处理大多数情况下的副作用操作,而 useUpdateEffect 是在某些特定场景下的补充工具。在大多数情况下,使用 useEffect 即可满足需求。

自定义useUpdateEffect

要自定义一个类似于 useUpdateEffect 的自定义 Hook,你可以借助 React 的 useEffectuseRef Hooks 来实现。以下是一个示例代码:

import { useEffect, useRef } from 'react';

function useUpdateEffect(effect, dependencies) {
  const isMounted = useRef(false);

  useEffect(() => {
    if (isMounted.current) {
      effect();
    } else {
      isMounted.current = true;
    }
  }, dependencies);
}

// 使用示例
function MyComponent() {
  const [count, setCount] = useState(0);

  useUpdateEffect(() => {
    console.log('Component has updated');
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

在上述示例中,我们创建了一个名为 useUpdateEffect 的自定义 Hook。它接受两个参数:effectdependencies。在内部,我们使用了 useRef 来创建一个标记是否已经完成初始渲染的变量 isMounted

useEffect 中,我们检查 isMounted 的值。如果 isMounted 的值为 true,则表示组件已经完成了初始渲染,此时执行传入的 effect 函数。否则,将 isMounted 的值设置为 true,表示组件已完成初始渲染。

在使用时,你可以像使用 useEffect 一样,传入 effect 函数和依赖项数组 dependencies,并且 effect 函数只会在组件更新时执行。

2、useTitle

useTitle 是一个相对经典的自定义 React Hook ,用来控制浏览器标题:

定义useTitle

import { useState, useEffect } from 'react';

function useTitle(initialTitle) {
  const [title, setTitle] = useState(initialTitle);
 
  useEffect(() => {
    document.title = title;
  }, [title]);

  return setTitle;
}

使用useTitle:

function Page() {
  const setTitle = useTitle('Default Title');
 
  return (
    <Button onClick={() => setTitle('New Title')}>
      Click me
    </Button>
  )
}

点击按钮后,浏览器标题会变成"New Title"。
它的工作原理是:

  • 保存标题的 state ,并记录修改 setTitle()
  • 用 useEffect 监测 title 变化,设置 document.title
    所以一旦我们调用 setTitle(‘New Title’) 改变 state ,useEffect 就会执行,设置新的浏览器标题。
    useTitle 的优点是:
  • 抽象出设置标题的逻辑,任何组件都可以共享
  • 让组件更纯粹,只需要调用 setTitle() 接口即可
    我们甚至可以抽象为更通用的 Hook:
js
function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
  }, [title]);
}

function Page() {
  useDocumentTitle('Default Title');
  // ...
}

通过自定义 Hook ,可以方便地在任何组件控制标题。

3、useForceUpdate

定义useForceUpdate

import { useState } from 'react';

function useForceUpdate() {
  const [value, setValue] = useState(0); 
  
  return () => {
    setValue(value => value + 1); 
  };
}

useForceUpdate的使用

const forceUpdate = useForceUpdate();

// 模拟更新组件
forceUpdate();

这个 Hook 返回了一个更新函数。在调用这个函数时,使用useState强制组件重新渲染。
这是基于以下原理实现的:

  • useState()会触发组件重新渲染
  • state变化后,组件函数会重新执行
    函数式组件只有 state 或 props 变化时才会更新。
    使用此 Hook 我们可以主动触发组件更新。
    比如在使用过时数据时:
// 过时数据 
const { data } = useSomeHook();

// 更新组件
const forceUpdate = useForceUpdate();
setInterval(() => {
  forceUpdate();
}, 5000);

每5秒强制组件一次,保证拿到最新数据。

4、useDebounce

定义

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);   
    }, delay);
    return () => {
      clearTimeout(handler); 
    };
  }, []); // 设为空数组[]

  useEffect(() => {
    clearTimeout(handler);     
    handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
  }, [value]);  // 只依赖 value

  return debouncedValue;
};

使用

const inputValue = useDebounced(searchTerm, 500);

这里 每当searchTerm变化时,会设置一个 500ms 的定时器。只有500ms内没有再改变searchTerm,才会更新debouncedValue
这实现了防抖功能:在一定时间内停止触发, 只执行最后的动作。

5、useThrottle

定义

const useThrottle = (value, limit) => {
  const [throttledValue, setThrottledValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setThrottledValue(value);
    }, limit);
    return () => {
      clearTimeout(handler);
    };
  }, []); // 应设为空数组[]  
  
  useEffect(() => {
    clearTimeout(handler);
    handler = setTimeout(() => {
      setThrottledValue(value);    
    }, limit);
  }, [value, limit]); 
  
  return throttledValue;  
};

使用

const throttledValue = useThrottle(inputValue, 1000);

这里 每次inputValue变化时,会开始一个计时器。1s后才会更新throttledValue,实现了节流功能。

6、useInterval

定义

const useInterval = (callback, delay) => {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }); 

  useEffect(() => {
    function tick() {
      savedCallback.current();          
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);        
      return () => clearInterval(id);
    }
  }, [delay]);
}

使用

useInterval(() => {
  // ...
}, 1000); 

这里每1000ms就会调用一次回调函数,实现了定时执行指定函数的功能。
有任何问题欢迎留言讨论学习文章来源地址https://www.toymoban.com/news/detail-532540.html

到了这里,关于react之自定义hooks的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 渗透测试方法论

    攻击与防御,攻击典型代表就是黑客入侵,非法的和渗透测试,合法的等工作。防御的典型代表等级保护、安全基线检查与加固、安全设备等。 渗透测试(penetration testing,pentest)是模拟黑客攻击,实施安全评估(即审计)的具体手段。方法论是在制定、实施信息安全审计方案时

    2024年02月11日
    浏览(55)
  • SOA认知和方法论

    在软件设计领域,企业架构通常被划分为如下五种分类: 如何理解架构分类依据及其彼此之间的关系?业务是企业赖以生存之本,因此业务架构是基础、是灵魂,其他一切均是对业务架构的支撑;根据业务架构形成与之相应的产品架构和数据架构;最后通过技术架构落地实施

    2024年02月08日
    浏览(52)
  • 论文阅读与管理方法论

    构建知识体系 通过Related Works快速了解该方向研究现状,追踪经典论文。 紧跟前沿技术 了解领域内新技术及效果,快速借鉴到自身项目。 培养科研逻辑 熟悉论文体系,了解如何快速创造新事物,培养良好的科研习惯。 写论文 面试找工作 快速熟悉某领域 发展历程 、 现状及

    2024年02月15日
    浏览(45)
  • 性能分析方法论简介

    限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 通常,我们是通过理论指导实践,而实践又反哺完善理论,二者缺一不可。 总的来说,性能优化是 从 时间 和 空间 两方面做出优化 ,然后取得一个可接受的平衡点。记住,无论怎么优

    2023年04月19日
    浏览(53)
  • 控制论与科学方法论

    《 控制论与科学方法论 》,真心不错。 书籍原文 电子版PDF :https://pan.quark.cn/s/00aa929e4433(分类在 学习 目录下) 备用链接:https://pan.xunlei.com/s/VNgj2vjW-Hf_543R2K8kbaifA1?pwd=2sap# 控制论是一种让系统按照我们想要的方式运行的方法。 以下是控制论、信息论、系统论的总结: 控制

    2024年01月25日
    浏览(36)
  • 黑盒测试方法论—边界值

    边界值分析法是一种很实用的黑盒测试用例方法,它具有很强的发现故障的能力。边界值分析法也是作为对等价类划分法的补充,测试用例来自等价类的边界。 这个方法其实是在测试实践当中发现,Bug 往往出现在定义域或值域的边界上,而不是在其内部。为检测边界附近的

    2024年02月11日
    浏览(54)
  • 数据建模方法论及实施步骤

    了解数据建模之前首先要知道的是什么是数据模型。数据模型(Data Model)是数据特征的抽象,它从抽象层次上描述了系统的静态特征、动态行为和约束条件,为数据库系统的信息表示与操作提供一个抽象的框架。 一、概要:数据建模简介 数据基本用于两种目的:1、操作型记

    2024年02月05日
    浏览(49)
  • SRE方法论之拥抱风险

    系统不可能100%可靠,人都不可能100%健康,更何况我们人类创造的系统?所以,任何软件系统都不应该一味地追求 100%可靠。事实证明,可靠性超过一定值后,再提高可靠性对于一项服务来说,结果可能会更差而不是更好!极端的可靠性会带来成本的大幅提升:比如过分追求稳

    2024年02月05日
    浏览(74)
  • MySQL的性能优化方法论

    作者:禅与计算机程序设计艺术 MySQL是一个开源的关系型数据库管理系统,由瑞典MySQL AB开发并发布。它的目的是为了快速、可靠地处理复杂的事务处理,支持多种编程语言,包括C、C++、Java、PHP、Python等。它是一个高效、可伸缩的数据库服务器,在Web应用方面也经常被应用到

    2024年02月06日
    浏览(50)
  • [渗透测试]—3.1 渗透测试方法论

    渗透测试(Penetration Testing)是一种模拟攻击者的行为,以评估系统安全性的方法。作为一名渗透测试工程师,了解渗透测试的方法论是非常重要的。在本章中,我们将详细介绍渗透测试的基本概念、方法论和常见工具。 渗透测试的主要目的是: 发现潜在的安全漏洞和风险

    2024年02月15日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包