網站首頁 編程語言 正文
任何相對獨立、復用性強的邏輯,都可以 extract 為自定義 Hook,自定義 Hook 是一種復用 React 的狀態邏輯的函數。
自定義 Hook 的主要特點是:
- 抽象組件間的狀態邏輯,方便復用
- 讓功能組件更純粹,更易于維護
- 自定義 Hook 可以調用其他 Hook
為什么要用自定義 Hook?
- 提煉能復用的邏輯
許多組件有相似的狀態邏輯,使用自定義 Hook 可以很方便地提取出來復用。 - 解決復雜組件的可讀性問題
使用自定義 Hook 將復雜組件拆分為更小的功能獨立的函數,有助于提高代碼的可讀性。 - 管理數據更新
使用獨立的 Hook 函數來管理數據請求、處理異步邏輯、數據緩存等,易于維護。 - 分離狀態邏輯
自定義 Hook 讓函數組件更純粹,只負責 UI,狀態邏輯則交給 Hook。 - 調用其他 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
的常見情況:
-
避免初始渲染時執行副作用:有些副作用操作可能只需要在組件更新時執行,例如發送網絡請求、更新特定狀態等。使用
useUpdateEffect
可以確保這些副作用操作在初始渲染時被跳過,只在組件更新時執行。 -
監聽特定狀態的變化:有時我們只關心特定狀態的變化,并希望在狀態發生變化時執行相應的操作。通過將狀態值作為
useUpdateEffect
的依賴項,可以確保副作用操作只在這些狀態發生變化時觸發。 -
更新外部資源或庫:有些第三方庫或外部資源可能需要在組件更新時進行更新或重新初始化。使用
useUpdateEffect
可以確保在組件更新時調用相應的函數或方法,以便正確地更新這些外部資源。
通過使用 useUpdateEffect
,我們可以更加精確地控制副作用操作的觸發時機,避免不必要的重復執行,以及在需要時處理特定的更新邏輯。
需要注意的是,React 自帶的 useEffect
可以處理大多數情況下的副作用操作,而 useUpdateEffect
是在某些特定場景下的補充工具。在大多數情況下,使用 useEffect
即可滿足需求。
自定義useUpdateEffect
要自定義一個類似于 useUpdateEffect
的自定義 Hook,你可以借助 React 的 useEffect
和 useRef
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。它接受兩個參數:effect
和 dependencies
。在內部,我們使用了 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
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-12-22 淺析Go語言中數組的這些細節_Golang
- 2022-03-23 C語言可變長的參數列表詳解_C 語言
- 2023-08-13 git版本管理常用命令
- 2023-04-07 C語言如何計算字符串長度_C 語言
- 2022-04-28 WPF使用Canvas畫布面板布局_實用技巧
- 2023-02-10 android?原生安全音量配置邏輯設計詳解_Android
- 2023-01-10 Qt實現可以計算大數的簡單計算器_C 語言
- 2022-07-13 Pycharm使用技巧_Pycharm配置autopep8
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支