React自定义 Hook

自定义 Hook

面向初学者的React自定义Hook问题:

1、什么是自定义Hook?

        自定义Hook是React 16.8版本中引入的新特性,让你在不编写class的情况下使用state以及其他的React特性。

        自定义Hook是一种自定义函数,它封装了React Hook的逻辑,并通过命名约定来使其可重用。自定义Hook可以用来解决组件之间共享的逻辑,例如处理表单的输入、状态管理、异步请求等。使用自定义Hook可以提高代码重用性和可读性,并让代码更易于测试和维护。自定义Hook的命名约定通常以"use"开头,例如"useForm"、"useFetch"等。

        通过自定义Hook,可以让你将组件之间的共享状态逻辑提取到可重用的函数中。它们不需要更改组件层次结构,而且不需要引入更深层次的嵌套组件来传递 props。这样可以使代码更加简洁和易于维护。

2、自定义Hook的基本规则是什么?

React 自定义 Hook 的基本规则包括:

  1. Hook 的名称必须以 "use" 开头,以示其为一个 Hook。

  2. Hook 内部只能调用其他的 Hook,不能调用其他的普通函数。

  3. Hook 必须在函数的最顶层使用,不能在循环、条件语句或者子函数中使用。

  4. 自定义 Hook 应该具有清晰的功能,而且要足够通用,方便在多个组件中使用。

  5. 由于自定义 Hook 本身就是一个函数,因此可以接受参数,也可以返回值。

  6. 自定义 Hook 中可以使用 useState、useEffect、useContext 等基础 Hook,也可以使用其他自定义 Hook。

  7. 自定义 Hook 一般应该是纯函数,不应该产生副作用。但如果需要产生副作用,可以使用 useLayoutEffect 或 useReducer 等 Hook 来实现。

3、如何创建和使用自定义Hook?

创建和使用自定义Hook的步骤大致如下:

  • 定义一个以"use"开头的函数。这是自定义Hook的规则,如果不遵循,React将无法自动检查你的Hook是否违反了Hook的规则。
  • 在自定义 Hook 中,你可以使用 useState、useEffect、useRef 等内置的 Hook,以及其他自定义 Hook。
  • 在你的React函数组件或者自定义Hook组件中使用这个自定义的Hook。

 React 允许开发者通过使用自定义 Hook 来重用组件逻辑。自定义 Hook 是一种 JavaScript 函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。

自定义 Hook 可以用来解决以下问题:

  1. 共享状态逻辑:例如用户认证状态、网络请求等。
  2. 处理副作用:例如订阅和取消订阅、定时器等。
  3. 抽象组件逻辑:例如表单处理、动画逻辑、业务逻辑等。

1、以下是一个关于网络请求 自定义 Hook 的示例:

import { useState, useEffect } from 'react';

const useFetchData = (url) => {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const data = await response.json();
        setData(data);
      } catch (error) {
        setError(error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, isLoading, error };
};

export default useFetchData;

这个自定义 Hook 是用来获取数据的。通过使用 useStateuseEffect Hook,我们可以获取到数据、设置加载状态和处理错误。最后通过 return 语句返回数据、加载状态和错误信息。

这个自定义 Hook 可以在组件中使用,如下所示:

import useFetchData from './useFetchData';

const App = () => {
  const { data, isLoading, error } = useFetchData('https://jsonplaceholder.typicode.com/todos/1');

  if (isLoading) {
    return 
Loading...
; } if (error) { return
Error: {error.message}
; } return (

{data.title}

{data.body}

); }; export default App;

在这个组件中,我们通过调用 useFetchData 自定义 Hook 获取数据。如果数据正在加载中,则显示 "Loading...";如果发生错误,则显示错误消息。最后,如果数据获取成功,则显示标题和正文。

2、自定义一个Hook 当resize 的时候 监听window的width和height的hook

import {useEffect, useState} from "react";

export const useWindowSize = () => {
    const [width, setWidth] = useState()
    const [height, setHeight] = useState()

    useEffect(() => {
        const {clientWidth, clientHeight} = document.documentElement
        setWidth(clientWidth)
        setHeight(clientHeight)
    }, [])

    useEffect(() => {
        const handleWindowSize = () =>{
            const {clientWidth, clientHeight} = document.documentElement
            setWidth(clientWidth)
            setHeight(clientHeight)
        };

        window.addEventListener('resize', handleWindowSize, false)

        return () => {
            window.removeEventListener('resize',handleWindowSize, false)
        }
    })

    return [width, height]
}

使用:

const [width, height] = useWindowSize()

3、一个官网的简单示例 

在自定义 Hook 中封装 Effect 

Effect 是一个 “逃生出口”:当你需要“走出 React 之外”或者当你的使用场景没有更好的内置解决方案时,你可以使用它们。如果你发现自己经常需要手动编写 Effect,那么这通常表明你需要为组件所依赖的通用行为提取一些 自定义 Hook。

例如,这个 useChatRoom 自定义 Hook 把 Effect 的逻辑“隐藏”在一个更具声明性的 API 之后:

function useChatRoom({ serverUrl, roomId }) {
    useEffect(() => {
        const options = {
            serverUrl: serverUrl,
            roomId: roomId
        };
        const connection = createConnection(options);
        connection.connect();

        return () => connection.disconnect();
    }, [roomId, serverUrl]);
}

然后你可以像这样从任何组件使用它:

function ChatRoom({ roomId }) {
    const [serverUrl, setServerUrl] = useState('https://localhost:1234');
    useChatRoom({
        roomId: roomId,
        serverUrl: serverUrl
    });
// ...

在 React 生态系统中,还有许多用于各种用途的优秀的自定义 Hook。

4、自定义Hook与普通的JavaScript函数有什么不同?

React 自定义 Hook 和普通 JavaScript 函数有以下不同:

        1. 命名规则:React 自定义 Hook 的名称必须以 "use" 开头,这是为了让 React 在编译时能够正确识别和处理它们。

        2. 使用规则:React 自定义 Hook 只能在函数组件或其他自定义 Hook 中使用,而普通 JavaScript 函数可以在任何地方使用。React 自定义 Hook 可以使用 React 内置的 Hook,比如 useState、useEffect 等,而普通 JavaScript 函数则不能使用这些 Hook。

        3. 使用场景:React 自定义 Hook 主要用于将组件中共用的逻辑抽离出来,方便复用和维护,而普通 JavaScript 函数则可以处理任何数据和业务逻辑。

        4. 内部实现:自定义Hook可以访问React的state和其他的React特性,而普通的JavaScript函数则不能。此外,每次在组件中调用自定义Hook,它都会获取独立的state。即使两个组件使用了相同的Hook,它们也不会共享state。这是因为自定义Hook是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义Hook时,其中的所有state和副作用都是完全隔离的。

总之,React 自定义 Hook 是 React 特有的一种函数,用于处理组件共用的逻辑,与普通 JavaScript 函数有些许不同。

5、什么是useEffect和useLayoutEffect,它们与自定义Hook有什么关系?

useEffect和useLayoutEffect是React中的两个用于处理副作用(side effects)的函数。useEffect在全部渲染完毕后才会执行,而useLayoutEffect则会在浏览器layout之后,painting(绘制)之前执行。它们与自定义Hook的关系在于,你可以在自定义Hook中使用这些函数来处理副作用,例如在useEffect中订阅事件并在useLayoutEffect中获取布局信息。

6、在使用自定义Hook时如何处理副作用?

在处理副作用时,可以将副作用封装到一个单独的函数中,然后在需要的地方调用这个函数。这样做可以确保副作用不会影响到其他的代码逻辑。同时,如果在一个组件中使用多个自定义Hook,每个Hook的副作用都是独立的,不会互相影响。

你可能感兴趣的:(react,javascript,前端,vue.js)