”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 在 React 中创建自定义 Hook 的最佳技巧

在 React 中创建自定义 Hook 的最佳技巧

发布于2024-11-07
浏览:697

Best Tips for Creating Custom Hooks in React

React 的自定义 Hooks 是从组件中删除可重用功能的有效工具。它们支持代码中的 DRY(不要重复)、可维护性和整洁性。但开发有用的自定义钩子需要牢牢掌握 React 的基本思想和推荐程序。在这篇文章中,我们将讨论在 React 中开发自定义钩子的一些最佳策略,并举例说明如何有效地应用它们。

1.了解 Hooks 的用途

在深入创建自定义钩子之前,了解什么是钩子以及它们存在的原因至关重要。 Hooks 允许您在功能组件中使用状态和其他 React 功能。自定义挂钩使您能够将组件逻辑提取到可重用函数中,这些函数可以在多个组件之间共享。

示例:基本自定义 Hook

这是管理计数器的自定义挂钩的简单示例:

import { useState } from 'react';

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

  const increment = () => setCount(prevCount => prevCount   1);
  const decrement = () => setCount(prevCount => prevCount - 1);
  const reset = () => setCount(initialValue);

  return { count, increment, decrement, reset };
}

// Usage in a component
// const { count, increment, decrement, reset } = useCounter(10);

2.遵循命名约定

React 有一个约定,自定义挂钩应以“use”一词开头。这不仅仅是一种风格选择——React 依赖于这个约定来自动应用钩子规则(比如不有条件地调用它们)。

提示:始终使用 use 来启动自定义钩子,以确保 React 知道它是一个钩子。

3.保持 Hooks 纯净

自定义钩子应该是纯函数,这意味着它们不应该有修改全局变量或直接与外部系统交互等副作用。如果需要副作用,例如进行 API 调用,则应使用内置的 React 钩子(如 useEffect.

)在钩子内处理它们。

示例:具有副作用的 Hook

import { useState, useEffect } from 'react';

function useFetchData(url) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, error, loading };
}

// Usage in a component
// const { data, error, loading } = useFetchData('https://api.example.com/data');

4。利用现有的 Hooks
创建自定义挂钩时,请确保利用现有的 React 挂钩,例如 useState、useEffect、useContext 等。这确保您的自定义钩子是可组合的,并且可以与 React 的内置功能无缝协作。

示例:组合 Hooks

这是一个结合了 useState 和 useEffect 来管理本地存储的自定义钩子:

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  useEffect(() => {
    try {
      window.localStorage.setItem(key, JSON.stringify(storedValue));
    } catch (error) {
      console.error(error);
    }
  }, [key, storedValue]);

  return [storedValue, setStoredValue];
}

// Usage in a component
// const [name, setName] = useLocalStorage('name', 'John Doe');

5。可重用性和组合

创建自定义挂钩的主要原因之一是提高可重用性。一个好的自定义钩子应该能够跨多个组件使用,而不需要进行大量修改。此外,钩子可以组合在一起以构建更复杂的逻辑。

提示:重点提取可能在多个组件中重用的逻辑。

6。记录你的 Hook

像任何代码一样,您的自定义挂钩应该有详细的文档记录。包括解释该钩子的作用、它接受什么参数、它返回什么以及它可能产生的任何副作用的注释。这使其他开发人员(以及未来的您)更容易正确理解和使用您的钩子。

示例:记录 Hook

/**
 * useCounter
 * 
 * A custom hook to manage a counter.
 *
 * @param {number} initialValue - Initial value of the counter.
 * @returns {object} { count, increment, decrement, reset } - Current count and functions to modify it.
 */
function useCounter(initialValue = 0) {
  // Implementation
}

7.测试你的 Hook

测试对于确保您的自定义挂钩按预期运行至关重要。使用 React-hooks-testing-library 或 Jest 等测试库为您的钩子编写单元测试。

示例:Hook 的基本测试

import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';

test('should increment and decrement counter', () => {
  const { result } = renderHook(() => useCounter(0));

  act(() => {
    result.current.increment();
  });

  expect(result.current.count).toBe(1);

  act(() => {
    result.current.decrement();
  });

  expect(result.current.count).toBe(0);
});

在整个应用程序中抽象和重用功能的一种有效技术是在 React 中使用自定义挂钩。您可以构建可靠且可维护的钩子,通过理解钩子的用途、遵守命名约定、保持钩子纯净、利用现有钩子、保证可重用性、文档化和测试来改进您的 React 开发过程。

版本声明 本文转载于:https://dev.to/wallacefreitas/best-tips-for-creating-custom-hooks-in-react-48ca?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • Android如何向PHP服务器发送POST数据?
    Android如何向PHP服务器发送POST数据?
    在android apache httpclient(已弃用) httpclient httpclient = new defaulthttpclient(); httppost httppost = new httppost(“ http://www.yoursite.com/script.p...
    编程 发布于2025-07-20
  • 如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求模拟浏览器行为,以及伪造的用户代理提供了一个用户 - 代理标头一个有效方法是提供有效的用户式header,以提供有效的用户 - 设置,该标题可以通过browser和Acterner Systems the equestersystermery和操作系统。通过模仿像Chro...
    编程 发布于2025-07-20
  • 如何有效地转换PHP中的时区?
    如何有效地转换PHP中的时区?
    在PHP 利用dateTime对象和functions DateTime对象及其相应的功能别名为时区转换提供方便的方法。例如: //定义用户的时区 date_default_timezone_set('欧洲/伦敦'); //创建DateTime对象 $ dateTime = ne...
    编程 发布于2025-07-20
  • Java字符串非空且非null的有效检查方法
    Java字符串非空且非null的有效检查方法
    检查字符串是否不是null而不是空的if (str != null && !str.isEmpty())Option 2: str.length() == 0For Java versions prior to 1.6, str.length() == 0 can be二手: if(str!= n...
    编程 发布于2025-07-20
  • Go语言垃圾回收如何处理切片内存?
    Go语言垃圾回收如何处理切片内存?
    Garbage Collection in Go Slices: A Detailed AnalysisIn Go, a slice is a dynamic array that references an underlying array.使用切片时,了解垃圾收集行为至关重要,以避免潜在的内存泄...
    编程 发布于2025-07-20
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,以便更快地搜索这些前缀。理解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-07-20
  • 如何使用node-mysql在单个查询中执行多个SQL语句?
    如何使用node-mysql在单个查询中执行多个SQL语句?
    在node-mysql node-mysql文档最初出于安全原因最初禁用多个语句支持,因为它可能导致SQL注入攻击。要启用此功能,您需要在创建连接时将倍增设置设置为true: var connection = mysql.createconnection({{multipleStatement:...
    编程 发布于2025-07-20
  • 如何使用替换指令在GO MOD中解析模块路径差异?
    如何使用替换指令在GO MOD中解析模块路径差异?
    在使用GO MOD时,在GO MOD 中克服模块路径差异时,可能会遇到冲突,其中3个Party Package将另一个PAXPANCE带有导入式套件之间的另一个软件包,并在导入式套件之间导入另一个软件包。如回声消息所证明的那样: go.etcd.io/bbolt [&&&&&&&&&&&&&&&&...
    编程 发布于2025-07-20
  • MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    MySQL中如何高效地根据两个条件INSERT或UPDATE行?
    在两个条件下插入或更新或更新 solution:的答案在于mysql的插入中...在重复键更新语法上。如果不存在匹配行或更新现有行,则此功能强大的功能可以通过插入新行来进行有效的数据操作。如果违反了唯一的密钥约束。实现所需的行为,该表必须具有唯一的键定义(在这种情况下为'名称'...
    编程 发布于2025-07-20
  • 在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    编程 发布于2025-07-20
  • 解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    解决MySQL插入Emoji时出现的\\"字符串值错误\\"异常
    Resolving Incorrect String Value Exception When Inserting EmojiWhen attempting to insert a string containing emoji characters into a MySQL database us...
    编程 发布于2025-07-20
  • PHP未来:适应与创新
    PHP未来:适应与创新
    PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。 引言在编程世界中,PHP一直是网页开发的中流砥柱。作为一个从1994年就开始发展...
    编程 发布于2025-07-20
  • 如何使用“ JSON”软件包解析JSON阵列?
    如何使用“ JSON”软件包解析JSON阵列?
    parsing JSON与JSON软件包 QUALDALS:考虑以下go代码:字符串 } func main(){ datajson:=`[“ 1”,“ 2”,“ 3”]`` arr:= jsontype {} 摘要:= = json.unmarshal([] byte(...
    编程 发布于2025-07-20
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-20

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3