欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解React自定義Hook

 更新時間:2023年04月21日 11:55:34   作者:Aphelios_  
在React項目中,我們經(jīng)常會使用到React自帶的幾個內(nèi)置Hooks,如 useState,useContext和useEffect。雖然在React中找不到這些 Hooks,但React提供了非常靈活的方式讓你為自己的需求來創(chuàng)建自己的自定義Hooks,想了解更多的,歡迎閱讀本文

前言

在 React 項目中,我們經(jīng)常會使用到 React 自帶的幾個內(nèi)置 Hooks,如 useState,useContext 和useEffect。但有時,我們可能希望有一個特定目的的 Hook :例如獲取數(shù)據(jù) useData,獲取連接 useConnect 等。雖然在 React 中找不到這些 Hooks,但 React 提供了非常靈活的方式讓你為自己的需求來創(chuàng)建自己的自定義 Hooks。

如何自定義 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 能夠減少重復的邏輯,更重要的是,自定義 Hooks 內(nèi)部的代碼描述了它們想做什么,而不是如何做。當你將邏輯提取到自定義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ù)組,包含當前的計數(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>
  );
}

在這個例子中,我們導入了 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>
  );
}

當我們點擊 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)變量中,當用戶進行某一操作 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,當調(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è)當連接成功時,你想將此邏輯移回你的組件:

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
}

現(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)。

總結(jié)

自定義 Hooks 可以幫助你遷移到更好的開發(fā)范式。通過將一些通用邏輯封裝在自定義 Hooks 中,你可以使組件代碼保持簡潔專注于核心意圖,這有助于減少重復性的代碼,并使你的代碼更易于維護更新,從而使你能夠更快速地開發(fā)新功能。

對于 Effect 而言,這樣可以使數(shù)據(jù)在 Effects 中流動的過程變得非常明確。這讓你的組件能夠專注于意圖,而不是 Effects 的具體實現(xiàn)。當 React 添加新功能時,你可以刪除那些 Effects 而不影響任何組件。就像設(shè)計系統(tǒng)一樣,你可能會發(fā)現(xiàn)從應用程序組件中提取常見習慣用法到自定義 Hooks 中是有非常幫助的。這將使你的組件代碼專注于意圖,并允許你避免頻繁編寫原始 Effects,這也是 React 開發(fā)者所推崇的。

以上就是詳解React自定義Hook的詳細內(nèi)容,更多關(guān)于React自定義Hook的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論