返回顶部
首页 > 资讯 > 前端开发 > 其他 >深入理解React的自定义Hook
  • 578
分享到

深入理解React的自定义Hook

前端代码规范React.js 2023-05-14 22:05:17 578人浏览 八月长安
摘要

自定义 Hooks 的核心是共享组件之间的逻辑。使用自定义 Hooks 能够减少重复的逻辑,更重要的是,自定义 Hooks 内部的代码描述了它们想做什么,而不是如何做。当你将逻辑提取到自定义Hooks 中时,你可以隐藏如何处理某些"

自定义 Hooks 的核心是共享组件之间的逻辑。使用自定义 Hooks 能够减少重复的逻辑,更重要的是,自定义 Hooks 内部的代码描述了它们想做什么,而不是如何做。当你将逻辑提取到自定义Hooks 中时,你可以隐藏如何处理某些"外部系统"或浏览器 api 的调用的细节,组件的代码表达的是你的意图,而不是实现细节。 下面是一个简单的例子:

import { useState } from 'React';
function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);
  function increment() {
    setCount(count + 1);
  }
  return [count, increment];
}

这个自定义 Hook 叫做 useCounter,它接受一个初始值作为参数,并返回一个数组,包含当前的计数值和一个增加计数的函数。 使用自定义 Hook 非常简单,只需要在函数组件中调用它即可。下面是一个使用 useCounter 的例子:

import React from 'react';
import useCounter from './useCounter';

function Counter() {
  const [count, increment] = useCounter(0);

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

在这个例子中,我们导入了 useCounter,并在组件中调用它。我们将返回的数组解构为 countincrement,然后在组件中使用它们。

自定义 Hooks 允许你共享有状态逻辑,而不是状态本身

自定义 Hooks 允许共享有状态逻辑,但不能共享状态本身。每个对 Hook 的调用都完全独立于对同一个 Hook 的其他调用。 以上面的 useCounter 为例:

import useCounter from './useCounter';
function Counter() {
	const [count1, increment1] = useCounter(0);
	const [count2, increment2] = useCounter(100);
  return (
    <div>
      <p>Count1: {count1}</p>
      <button onClick={increment1}>Increment1</button>
       <p>Count2: {count2}</p>
      <button onClick={increment2}>Increment2</button>
    </div>
  );
}

当我们点击 Increment2 时,并不会影响 count1 ,因为每一个 useCounter 的调用都是独立的,其内部状态也是独立的。

分类

功能型 Hooks

以实现特定功能或目的,与具体业务无关:

useWindowWidth

该 hook 返回窗口宽度的值。

import { useState, useEffect } from 'react';
function useWindowWidth() {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);
  useEffect(() => {
    const handleResize = () => setWindowWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return windowWidth;
}

useLocalStorage

该 hook 允许你在本地存储中存储和检索值。

import { useState } 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.log(error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, jsON.stringify(value));
    } catch (error) {
      console.log(error);
    }
  };

  return [storedValue, setValue];
}

业务型 Hooks

useFetch

该 hook 允许你从 API 中获取数据。

import { useState, useEffect } from 'react';
function useFetch(url) {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const json = await response.json();
        setData(json);
      } catch (error) {
        setError(error);
      } finally {
        setIsLoading(false);
      }
    };
    fetchData();
  }, [url]);
  return { data, error, isLoading };
}

useModal

该 hook 允许你管理模态对话框的状态。

//useFetch.js
import {useState, useEffect} from 'react'
//don't forget to give a url parameter for the function.
const useFetch = (url)=>{
  const [data, setData] = useState([])
  const getData = async ()=>{
    const response = await fetch(url)
    const userdata = await response.json()
    setData(userdata)
  }
 useEffect(()=>{
    getData()
  },[url])
  //return data that we will need in other components.
  return {data};
}
export default useFetch;

在多个 Hook 之间传递信息

由于 Hook 本身就是函数,因此我们可以在它们之间传递信息。下面我们以 useUserInfo 获取用户信息 为例:

//useUserInfo.jsx
import { useEffect,useState } from 'react'
const useUserInfo = (userId) => {
  const [userInfo, setUserInfo] = useState({})
  useEffect(() => {
    fetch('/user')
      .then(res => res.json())
      .then(data => setUserInfo(data))
  }, [userId])
  return userInfo
}
//Home.jsx
...
const Home = ()=>{
	const [userId,setUserId] = useState('103')
	const useInfo = useUserInfo(userId)
	return (
	  <>
	     <div>name:{userInfo.name}</div>
	     <div>age:{userInfo.age}</div>
	     ...
	  </> 
	)
}

我们将 用户 id 保存在 userId 状态变量中,当用户进行某一操作 setUserId 时,由于 useState 为我们提供了 userId 状态变量的最新值,因此我们可以将它作为参数传递给自定义的 useUserInfo Hook:

const [userId,setUserId] = useState('103')
const userInfo = useUserInfo(userId)

此时,我们的 userInfo 会随着 userId 的改变而更新。

将 event handlers 传递给自定义 Hooks

This section describes an experimental API that has not yet been released in a stable version of React. 本节描述了一个尚未在 React 稳定版本中发布的 实验性 API。

你可能希望让组件自定义其行为,而不是完全地将逻辑封装 Hooks 中,我们可以通过将 event handlers 作为参数传递给 Hooks,下面是一个聊天室的例子:useChatRoom 接受一个服务端 url 和 roomId,当调用这个 Hook 的时候,会进行连接,

export function useChatRoom({ serverUrl, roomId }) {
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    connection.on('message', (msg) => {
      showNotification('New message: ' + msg);
    });
    return () => connection.disconnect();
  }, [roomId, serverUrl]);
}

假设当连接成功时,你想将此逻辑移回你的组件:

export default function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');
  useChatRoom({
    roomId: roomId,
    serverUrl: serverUrl,
    onReceiveMessage(msg) {
      showNotification('New message: ' + msg);
    }
  });
  // ...

要做到这一点,改变你的自定义 Hook ,把 onReceiveMessage 作为它的命名选项之一:

export function useChatRoom({ serverUrl, roomId, onReceiveMessage }) {
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    connection.on('message', (msg) => {
      onReceiveMessage(msg);
    });
    return () => connection.disconnect();
  }, [roomId, serverUrl, onReceiveMessage]); // ✅ All dependencies declared
}

这可以工作,但是当你的自定义 Hook 接受事件处理程序时,你还可以做一个改进。 在 onReceiveMessage 上添加依赖并不理想,因为它会导致每次组件重新渲染时聊天都重新连接。将此事件处理程序包装到 EffectEvent 中以将其从依赖项中移除:

import { useEffect, useEffectEvent } from 'react';  
// ...
export function useChatRoom({ serverUrl, roomId, onReceiveMessage }) {
  const onMessage = useEffectEvent(onReceiveMessage);
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    connection.on('message', (msg) => {
      onMessage(msg);
    });
    return () => connection.disconnect();
  }, [roomId, serverUrl]); // ✅ All dependencies declared
}

现在不会在每次重新渲染聊天室组件时进行重新连接。

开源 React Hooks 库

  • ahooks 一套由阿里巴巴开源的 React Hooks 库,封装了大量好用的 Hooks。
  • react-use 一个必不可少的 React Hooks 集合。其包含了传感器、用户界面、动画效果、副作用、生命周期、状态这六大类的Hooks。
  • useHooks 一组易于理解的 React Hook集合。
  • react-recipes 一个包含流行的自定义 Hook 的 React Hooks 实用程序库。
  • Rhooks 一组基本的 React 自定义Hooks。
  • react-hanger 一组有用的 hooks,用于特定于某些基本类型的状态更改辅助函数。
  • Beautiful React Hook 一组漂亮的(希望有用的)React hooks 来加速你的组件和 hooks 开发
  • Awesome React Hooks 一个很棒的 React Hooks 资源集合,该集合包含React Hooks教程、视频、工具,Hooks列表。其中Hooks列表中包含了众多实用的自定义Hooks。
  • SWR 一个用于获取数据的 React Hooks 库。只需一个Hook,就可以显着简化项目中的数据获取逻辑。
  • React Hook FORM 一个用于表单状态管理和验证的 React Hooks (WEB + React Native)。

总结

自定义 Hooks 可以帮助你迁移到更好的开发范式。通过将一些通用逻辑封装在自定义 Hooks 中,你可以使组件代码保持简洁专注于核心意图,这有助于减少重复性的代码,并使你的代码更易于维护更新,从而使你能够更快速地开发新功能。

对于 Effect 而言,这样可以使数据在 Effects 中流动的过程变得非常明确。这让你的组件能够专注于意图,而不是 Effects 的具体实现。当 React 添加新功能时,你可以删除那些 Effects 而不影响任何组件。就像设计系统一样,你可能会发现从应用程序组件中提取常见习惯用法到自定义 Hooks 中是有非常帮助的。这将使你的组件代码专注于意图,并允许你避免频繁编写原始 Effects,这也是 React 开发者所推崇的。

学习视频分享:编程基础视频)

以上就是深入理解React的自定义Hook的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: 深入理解React的自定义Hook

本文链接: https://lsjlt.com/news/207710.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 深入理解React的自定义Hook
    自定义 Hooks 的核心是共享组件之间的逻辑。使用自定义 Hooks 能够减少重复的逻辑,更重要的是,自定义 Hooks 内部的代码描述了它们想做什么,而不是如何做。当你将逻辑提取到自定义Hooks 中时,你可以隐藏如何处理某些"...
    99+
    2023-05-14
    前端 代码规范 React.js
  • 详解React自定义Hook
    目录前言如何自定义 Hooks组件之间共享逻辑自定义 Hooks 允许你共享有状态逻辑,而不是状态本身分类功能型 HooksuseWindowWidthuseLocalStorage...
    99+
    2023-05-17
    React自定义Hook React Hook
  • React自定义hook的方法
    目录什么是hook常用的有哪些hook自定义hook什么是hook Hook是 React 16.8 的新增特性。它通常与函数式组件同时使用。可以使函数式组件在不编写 class 的...
    99+
    2024-04-02
  • React如何自定义hook
    本篇内容主要讲解“React如何自定义hook”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React如何自定义hook”吧!什么是hookHook是 React 16.8 的新增特性。它通常与...
    99+
    2023-07-02
  • React Native自定义路由管理的深入理解
    目录1、自定义路由2、Tab导航3、数据回传总结1、自定义路由 众所周知,不管是在原生Android还是iOS,它们都有一个默认的路由路由栈管理类。由于React Native官方...
    99+
    2024-04-02
  • react实现自定义拖拽hook
    前沿 最近发现公司的产品好几个模块用到了拖拽功能,之前拖拽组件是通过Html5 drag Api 实现的但体验并不是很好,顺便将原来的拖拽组建稍做修改,写一个自定义hook,方便大家...
    99+
    2024-04-02
  • React自定义Hook-useForkRef的具体使用
    目录开篇思路实现自定义 Hook - useForkRef开篇 使用过 React 技术栈的同学相信都使用过 ref 传递给 render 中的元素,而在使用 React 封装组件时...
    99+
    2024-04-02
  • 深入理解Java:注解(Annotation)自定义注解入门
     要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。元注解:  元注解的作用就是负责注解其他注解。Java5.0定...
    99+
    2024-04-02
  • 详解Vue 自定义hook 函数
    目录定义使用封装发ajax请求的hook函数(ts版本)定义 什么是hook 本质是一个函数,把 setup 函数中使用的 Composition API (组合API)进行了封装类...
    99+
    2024-04-02
  • 深入解析Vue的自定义指令
    目录介绍​指令钩子​钩子参数​简化形式​对象字面量​在组件上使用​介绍​ 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之...
    99+
    2023-05-18
    Vue 指令 Vue自定义指令
  • 深入理解注解与自定义注解的一些概念
    一、注解介绍 注解就是一种标记符号,可以在代码上的关键节点(类、方法、变量、参数、包)打上标记,然后程序在编译时或者运行时就可以检测到这些标记从而执行一些自己需要的功能操作。 自定义...
    99+
    2024-04-02
  • Android自定义属性 format的深入解析
    1. reference:参考某一资源ID。(1)属性定义: 代码如下:<declare-styleable name = "名称">   &l...
    99+
    2022-06-06
    format 属性 Android
  • 深入了解Vue中的自定义指令
    作为使用Vue的开发者,我们对Vue指令一定不陌生,诸如v-model、v-on、v-for、v-if等,同时Vue也为开发者提供了自定义指令的api,熟练的使用自定义指令可以极大的提高了我们编写代码的效率,让我们可以节省时间开心的摸鱼~对...
    99+
    2022-11-22
    Vue.js
  • 自定义Hook的方法有哪些
    这篇文章主要介绍“自定义Hook的方法有哪些”,在日常操作中,相信很多人在自定义Hook的方法有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”自定义Hook的方法有哪些”...
    99+
    2024-04-02
  • vue3的自定义hook函数使用
    目录自定义hook函数使用vue3 hooks函数示例官方示例代码---封装前使用hooks函数封装后hooks函数自定义hook函数使用 使用Vue3的组合API封装的可复用的功能...
    99+
    2024-04-02
  • 深入理解React State 原理
    目录问题:setState 到底是同步还是异步的?类组件statesetState原理揭秘函数组件state问题:setState 到底是同步还是异步的? 如果对 React 底层有...
    99+
    2024-04-02
  • 怎样深入理解react
    这篇文章给大家介绍怎样深入理解react,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。理解ReactElement和ReactClass的概念首先让我们理解两个概念:ReactElem...
    99+
    2024-04-02
  • React深入了解原理
    目录VDOM(虚拟dom)Fiber架构初始化渲染更新时render阶段commit阶段VDOM(虚拟dom) react和vue都是基于vdom的前端框架。 web界面由DOM树来...
    99+
    2024-04-02
  • vue3 hook自动导入原理解析
    目录1. vue3 自动导入2. API 的 自动引入Ⅰ、使用前后对比Ⅱ、安装三方件Ⅲ、配置三方件3. 组件的自动引入Ⅰ、使用前后对比Ⅱ、安装三方件Ⅲ、配置三方件1. vue3 自动...
    99+
    2024-04-02
  • 深入理解Java中包的定义与使用
    目录包是什么?包的作用导入包中的类自定义包包的访问权限控制包是什么? 在开发过程中,会定义很多类,随着类越写越多,难免会出现类重名而发生覆盖的情况,为了在使用它们的时候不让编译器混淆...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作