日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

react之自定義hooks

作者:heiyay 更新時間: 2023-07-03 編程語言

任何相對獨立、復用性強的邏輯,都可以 extract 為自定義 Hook,自定義 Hook 是一種復用 React 的狀態邏輯的函數。
自定義 Hook 的主要特點是:

  • 抽象組件間的狀態邏輯,方便復用
  • 讓功能組件更純粹,更易于維護
  • 自定義 Hook 可以調用其他 Hook

為什么要用自定義 Hook?

  1. 提煉能復用的邏輯
    許多組件有相似的狀態邏輯,使用自定義 Hook 可以很方便地提取出來復用。
  2. 解決復雜組件的可讀性問題
    使用自定義 Hook 將復雜組件拆分為更小的功能獨立的函數,有助于提高代碼的可讀性。
  3. 管理數據更新
    使用獨立的 Hook 函數來管理數據請求、處理異步邏輯、數據緩存等,易于維護。
  4. 分離狀態邏輯
    自定義 Hook 讓函數組件更純粹,只負責 UI,狀態邏輯則交給 Hook。
  5. 調用其他 Hook
    自定義 Hook 本身還可以調用 useState、useEffect 等其他 React Hook。

以下是我總結的一些常用的hooks

1、useUpdateEffect

useUpdateEffect作用

useUpdateEffect 是一個自定義的 React Hook,用于在組件更新時執行副作用操作。它類似于 React 的 useEffect,但是會忽略組件的初始渲染階段,只在組件更新時執行副作用操作。

在 React 中,useEffect 會在組件的每次渲染(包括初始渲染)完成后執行副作用操作。但有時候我們只想在組件更新時執行某些操作,而不關心初始渲染階段的操作。這就是 useUpdateEffect 的用途。

以下是一個示例:

import { useEffect, useState } from 'react';

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

  useEffect(() => {
    console.log('useEffect - Component has rendered');
  });

  useUpdateEffect(() => {
    console.log('useUpdateEffect - Component has updated');
  });

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

在上述示例中,當點擊 “Increment” 按鈕時,count 的值會增加并觸發組件的重新渲染。useEffect 會在每次渲染后執行,而 useUpdateEffect 只會在組件更新時執行。

通過使用 useUpdateEffect,你可以在組件更新時執行一些特定的副作用操作,如請求數據、更新狀態等,而不需要關心初始渲染階段的操作。

為什么會需要用到useUpdateEffect

在某些情況下,我們希望在 React 組件更新時執行一些特定的副作用操作,而不在初始渲染階段執行這些操作。這種情況下,我們可以使用類似于 useUpdateEffect 的自定義 Hook。

以下是一些使用 useUpdateEffect 的常見情況:

  1. 避免初始渲染時執行副作用:有些副作用操作可能只需要在組件更新時執行,例如發送網絡請求、更新特定狀態等。使用 useUpdateEffect 可以確保這些副作用操作在初始渲染時被跳過,只在組件更新時執行。

  2. 監聽特定狀態的變化:有時我們只關心特定狀態的變化,并希望在狀態發生變化時執行相應的操作。通過將狀態值作為 useUpdateEffect 的依賴項,可以確保副作用操作只在這些狀態發生變化時觸發。

  3. 更新外部資源或庫:有些第三方庫或外部資源可能需要在組件更新時進行更新或重新初始化。使用 useUpdateEffect 可以確保在組件更新時調用相應的函數或方法,以便正確地更新這些外部資源。

通過使用 useUpdateEffect,我們可以更加精確地控制副作用操作的觸發時機,避免不必要的重復執行,以及在需要時處理特定的更新邏輯。

需要注意的是,React 自帶的 useEffect 可以處理大多數情況下的副作用操作,而 useUpdateEffect 是在某些特定場景下的補充工具。在大多數情況下,使用 useEffect 即可滿足需求。

自定義useUpdateEffect

要自定義一個類似于 useUpdateEffect 的自定義 Hook,你可以借助 React 的 useEffectuseRef Hooks 來實現。以下是一個示例代碼:

import { useEffect, useRef } from 'react';

function useUpdateEffect(effect, dependencies) {
  const isMounted = useRef(false);

  useEffect(() => {
    if (isMounted.current) {
      effect();
    } else {
      isMounted.current = true;
    }
  }, dependencies);
}

// 使用示例
function MyComponent() {
  const [count, setCount] = useState(0);

  useUpdateEffect(() => {
    console.log('Component has updated');
  }, [count]);

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

在上述示例中,我們創建了一個名為 useUpdateEffect 的自定義 Hook。它接受兩個參數:effectdependencies。在內部,我們使用了 useRef 來創建一個標記是否已經完成初始渲染的變量 isMounted

useEffect 中,我們檢查 isMounted 的值。如果 isMounted 的值為 true,則表示組件已經完成了初始渲染,此時執行傳入的 effect 函數。否則,將 isMounted 的值設置為 true,表示組件已完成初始渲染。

在使用時,你可以像使用 useEffect 一樣,傳入 effect 函數和依賴項數組 dependencies,并且 effect 函數只會在組件更新時執行。

2、useTitle

useTitle 是一個相對經典的自定義 React Hook ,用來控制瀏覽器標題:

定義useTitle

import { useState, useEffect } from 'react';

function useTitle(initialTitle) {
  const [title, setTitle] = useState(initialTitle);
 
  useEffect(() => {
    document.title = title;
  }, [title]);

  return setTitle;
}

使用useTitle:

function Page() {
  const setTitle = useTitle('Default Title');
 
  return (
    <Button onClick={() => setTitle('New Title')}>
      Click me
    </Button>
  )
}

點擊按鈕后,瀏覽器標題會變成"New Title"。
它的工作原理是:

  • 保存標題的 state ,并記錄修改 setTitle()
  • 用 useEffect 監測 title 變化,設置 document.title
    所以一旦我們調用 setTitle(‘New Title’) 改變 state ,useEffect 就會執行,設置新的瀏覽器標題。
    useTitle 的優點是:
  • 抽象出設置標題的邏輯,任何組件都可以共享
  • 讓組件更純粹,只需要調用 setTitle() 接口即可
    我們甚至可以抽象為更通用的 Hook:
js
function useDocumentTitle(title) {
  useEffect(() => {
    document.title = title;
  }, [title]);
}

function Page() {
  useDocumentTitle('Default Title');
  // ...
}

通過自定義 Hook ,可以方便地在任何組件控制標題。

3、useForceUpdate

定義useForceUpdate

import { useState } from 'react';

function useForceUpdate() {
  const [value, setValue] = useState(0); 
  
  return () => {
    setValue(value => value + 1); 
  };
}

useForceUpdate的使用

const forceUpdate = useForceUpdate();

// 模擬更新組件
forceUpdate();

這個 Hook 返回了一個更新函數。在調用這個函數時,使用useState強制組件重新渲染。
這是基于以下原理實現的:

  • useState()會觸發組件重新渲染
  • state變化后,組件函數會重新執行
    函數式組件只有 state 或 props 變化時才會更新。
    使用此 Hook 我們可以主動觸發組件更新。
    比如在使用過時數據時:
// 過時數據 
const { data } = useSomeHook();

// 更新組件
const forceUpdate = useForceUpdate();
setInterval(() => {
  forceUpdate();
}, 5000);

每5秒強制組件一次,保證拿到最新數據。

4、useDebounce

定義

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);   
    }, delay);
    return () => {
      clearTimeout(handler); 
    };
  }, []); // 設為空數組[]

  useEffect(() => {
    clearTimeout(handler);     
    handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
  }, [value]);  // 只依賴 value

  return debouncedValue;
};

使用

const inputValue = useDebounced(searchTerm, 500);

這里 每當searchTerm變化時,會設置一個 500ms 的定時器。只有500ms內沒有再改變searchTerm,才會更新debouncedValue
這實現了防抖功能:在一定時間內停止觸發, 只執行最后的動作。

5、useThrottle

定義

const useThrottle = (value, limit) => {
  const [throttledValue, setThrottledValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setThrottledValue(value);
    }, limit);
    return () => {
      clearTimeout(handler);
    };
  }, []); // 應設為空數組[]  
  
  useEffect(() => {
    clearTimeout(handler);
    handler = setTimeout(() => {
      setThrottledValue(value);    
    }, limit);
  }, [value, limit]); 
  
  return throttledValue;  
};

使用

const throttledValue = useThrottle(inputValue, 1000);

這里 每次inputValue變化時,會開始一個計時器。1s后才會更新throttledValue,實現了節流功能。

6、useInterval

定義

const useInterval = (callback, delay) => {
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }); 

  useEffect(() => {
    function tick() {
      savedCallback.current();          
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);        
      return () => clearInterval(id);
    }
  }, [delay]);
}

使用

useInterval(() => {
  // ...
}, 1000); 

這里每1000ms就會調用一次回調函數,實現了定時執行指定函數的功能。
有任何問題歡迎留言討論學習

原文鏈接:https://blog.csdn.net/study_way/article/details/131477832

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新