溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

React中怎么自定義Hook

發(fā)布時間:2023-04-21 14:21:35 來源:億速云 閱讀:183 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“React中怎么自定義Hook”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“React中怎么自定義Hook”吧!

    如何自定義 Hooks

    在 React 中你必須遵循以下命名約定:

    • React Component: React 組件名稱必須以大寫字母開頭,如 StatusBar 和 SaveButton。React組件還需要 返回 一些React知道如何渲染的東西,比如 JSX 。

    • React Hook: Hook 名必須以 use 開頭,后面跟著一個大寫字母,比如 useState (內(nèi)置)或useStatus (自定義)。與 React 組件不同的是自定義 Hook 可以返回任意值。

    這個命名約定確保你始終可以查看組件,并了解其狀態(tài)、效果以及其他 React 特性可能“隱藏”的位置。例如,如果你在組件中看到 getColor() 函數(shù)調(diào)用,你可以確定它不可能包含 React state,因為其名稱不以use開頭。但是,像 useStatus() 這樣的函數(shù)調(diào)用很可能包含對其他 Hooks 的調(diào)用!

    組件之間共享邏輯

    The code inside them describes what they want to do rather than how to do it .

    自定義 Hooks 的核心是共享組件之間的邏輯。使用自定義 Hooks 能夠減少重復(fù)的邏輯,更重要的是,自定義 Hooks 內(nèi)部的代碼描述了它們想做什么,而不是如何做。當(dāng)你將邏輯提取到自定義Hooks 中時,你可以隱藏如何處理某些"外部系統(tǒng)"或瀏覽器 API 的調(diào)用的細節(jié),組件的代碼表達的是你的意圖,而不是實現(xiàn)細節(jié)。 下面是一個簡單的例子:

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

    這個自定義 Hook 叫做 useCounter,它接受一個初始值作為參數(shù),并返回一個數(shù)組,包含當(dāng)前的計數(shù)值和一個增加計數(shù)的函數(shù)。 使用自定義 Hook 非常簡單,只需要在函數(shù)組件中調(diào)用它即可。下面是一個使用 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>
      );
    }

    在這個例子中,我們導(dǎo)入了 useCounter,并在組件中調(diào)用它。我們將返回的數(shù)組解構(gòu)為 count 和 increment,然后在組件中使用它們。

    自定義 Hooks 允許你共享有狀態(tài)邏輯,而不是狀態(tài)本身

    自定義 Hooks 允許共享有狀態(tài)邏輯,但不能共享狀態(tài)本身。每個對 Hook 的調(diào)用都完全獨立于對同一個 Hook 的其他調(diào)用。 以上面的 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>
      );
    }

    當(dāng)我們點擊 Increment2 時,并不會影響 count1 ,因為每一個 useCounter 的調(diào)用都是獨立的,其內(nèi)部狀態(tài)也是獨立的。

    分類

    功能型 Hooks

    以實現(xiàn)特定功能或目的,與具體業(yè)務(wù)無關(guān):

    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];
    }

    業(yè)務(wù)型 Hooks

    useFetch

    該 hook 允許你從 API 中獲取數(shù)據(jù)。

    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 允許你管理模態(tài)對話框的狀態(tài)。

    //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 本身就是函數(shù),因此我們可以在它們之間傳遞信息。下面我們以 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 狀態(tài)變量中,當(dāng)用戶進行某一操作 setUserId 時,由于 useState 為我們提供了 userId 狀態(tài)變量的最新值,因此我們可以將它作為參數(shù)傳遞給自定義的 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. 本節(jié)描述了一個尚未在 React 穩(wěn)定版本中發(fā)布的 實驗性 API。

    你可能希望讓組件自定義其行為,而不是完全地將邏輯封裝 Hooks 中,我們可以通過將 event handlers 作為參數(shù)傳遞給 Hooks,下面是一個聊天室的例子: useChatRoom 接受一個服務(wù)端 url 和 roomId,當(dāng)調(diào)用這個 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]);
    }

    假設(shè)當(dāng)連接成功時,你想將此邏輯移回你的組件:

    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
    }

    這可以工作,但是當(dāng)你的自定義 Hook 接受事件處理程序時,你還可以做一個改進。 在 onReceiveMessage 上添加依賴并不理想,因為它會導(dǎo)致每次組件重新渲染時聊天都重新連接。將此事件處理程序包裝到 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
    }

    現(xiàn)在不會在每次重新渲染聊天室組件時進行重新連接。

    開源 React Hooks 庫

    • ahooks 一套由阿里巴巴開源的 React Hooks 庫,封裝了大量好用的 Hooks。

    • react-use 一個必不可少的 React Hooks 集合。其包含了傳感器、用戶界面、動畫效果、副作用、生命周期、狀態(tài)這六大類的Hooks。

    • useHooks 一組易于理解的 React Hook集合。

    • react-recipes 一個包含流行的自定義 Hook 的 React Hooks 實用程序庫。

    • Rhooks 一組基本的 React 自定義Hooks。

    • react-hanger 一組有用的 hooks,用于特定于某些基本類型的狀態(tài)更改輔助函數(shù)。

    • Beautiful React Hook 一組漂亮的(希望有用的)React hooks 來加速你的組件和 hooks 開發(fā)。

    • Awesome React Hooks 一個很棒的 React Hooks 資源集合,該集合包含React Hooks教程、視頻、工具,Hooks列表。其中Hooks列表中包含了眾多實用的自定義Hooks。

    • SWR 一個用于獲取數(shù)據(jù)的 React Hooks 庫。只需一個Hook,就可以顯著簡化項目中的數(shù)據(jù)獲取邏輯。

    • React Hook Form 一個用于表單狀態(tài)管理和驗證的 React Hooks (Web + React Native)。

    感謝各位的閱讀,以上就是“React中怎么自定義Hook”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對React中怎么自定義Hook這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

    向AI問一下細節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI