網站首頁 編程語言 正文
React的useEffect Hook
可以讓用戶處理應用程序的副作用
。例如:
-
從網絡獲取數據
:應用程序通常在第一次加載時獲取并填充數據。這可以通過useEffect
函數實現 -
操作UI
:應用程序應該響應按鈕點擊事件(例如,打開一個菜單) -
設置或結束計時器
:如果某個變量達到預定義值,則內置計時器應自行停止或啟動
盡管useEffect Hook在React生態系統中很常見,但它需要時間來掌握。因此,許多新手開發人員在配置他們的useEffect函數時,會導致無限循環問題。在本文中,您將了解不同場景下帶來的無限循環問題以及如何解決它們。
這是我們今天要學習的內容:
是什么導致無限循環以及如何解決它們:
- 在依賴項數組中不傳遞依賴項
- 使用函數作為依賴項
- 使用數組作為依賴項
- 使用對象作為依賴項
- 傳遞不正確的依賴項
什么導致的無限循環以及如何解決它們
在依賴項數組中不傳遞依賴項
如果您的useEffect函數不包含任何依賴項,則會出現一個無限循環。
例如,看看下面的代碼:
function App() { const [count, setCount] = useState(0); //初始化值 useEffect(() => { setCount((count) => count + 1); }); //無依賴項 return ( <div className="App"> <p> value of count: {count} </p> </div> ); }
如果沒有依賴關系,則默認在每個更新周期上觸發useEffect。因此,這里的應用程序將在每次渲染時執行setCount函數。因此,這會導致一個無限循環:
是什么導致了這個問題?讓我們一步一步來分析這個問題:
- 在第一次渲染時,React會檢查
count
的值。在這里,由于count為0,程序執行useEffect函數 - 稍后,useEffect調用setCount方法并更新count的值
- 之后,React重新呈現UI以顯示count的更新值
- 此外,由于
useEffect在每個呈現周期中運行
,它將重新調用setCount函數
- 由于上述步驟發生在每一個渲染,這導致你的應用程序崩潰
如何解決這個問題
為了緩解這個問題,我們必須使用依賴數組,告訴React只有在特定值更新時才調用useEffect。
下一步,像這樣附加一個空白數組作為依賴項:
useEffect(() => { setCount((count) => count + 1); }, []); //empty array as second argument.
這告訴React在第一次裝載時執行setCount
函數。
使用函數作為依賴項
如果你把一個方法傳入你的useEffect
依賴數組,React會拋出一個錯誤,表明你有一個無限循環:
function App() { const [count, setCount] = useState(0); function logResult() { return 2 + 2; } useEffect(() => { setCount((count) => count + 1); }, [logResult]); // 函數作為依賴項 return ( <div className="App"> <p> value of count: {count} </p> </div> ); }
在這段代碼中,我們將logResult
方法傳遞給useEffect
數組。理論上,React只需要在第一次渲染時增加count
的值。
是什么導致了這個問題?
- 要記住的一件事是,useEffect使用了一個叫做淺比較的概念。它這樣做是為了驗證依賴項是否已經更新
- 這里的問題是,在每次呈現期間,React都會重新定義logResult的引用
- 因此,這將在每個循環中重新觸發useEffect函數
- 因此,React會調用setCount鉤子,直到應用程序遇到更新深度錯誤。這會給程序帶來錯誤和不穩定性
如何解決這個問題
一個解決方案是使用useCallback
鉤子。這允許開發人員記住他們的函數,從而確保引用值保持不變。由于這個參考值是穩定的,React不應該無限地重新渲染UI:
const logResult = useCallback(() => { return 2 + 2; }, []); // logResult是緩存的 useEffect(()=> { setCount((count)=> count+1); },[logResult]); //沒有無限循環錯誤,因為logResult引用保持不變。
結果:
使用數組作為依賴項
將數組變量傳遞給依賴項也會運行一個無限循環??紤]下面的代碼示例:
const [count, setCount] = useState(0); //初始值為0。 const myArray = ["one", "two", "three"]; useEffect(() => { setCount((count) => count + 1); // 和前面一樣,增加Count的值 }, [myArray]); // 將數組變量傳遞給依賴項
在這個塊中,我們將myArray變量傳入依賴參數。
是什么導致了這個問題?
既然myArray的值在整個程序中都沒有改變,為什么我們的代碼會多次觸發useEffect ?
- 在這里,回想一下React使用淺比較來檢查依賴項的引用是否發生了變化。
- 由于對myArray的引用在每次渲染時都在變化,useEffect將觸發setCount回調
- 因此,由于myArray的引用值不穩定,React將在每個渲染周期中調用useEffect。最終,這會導致應用程序崩潰
如何解決這個問題
為了解決這個問題,我們可以使用useRefHook。這將返回一個可變對象,確保引用不會改變:
const [count, setCount] = useState(0); //提取“current”屬性并給它賦值 const { current: myArray } = useRef(["one", "two", "three"]); useEffect(() => { setCount((count) => count + 1); }, [myArray]); //依賴值是穩定的,所以沒有無限循環
將對象作為依賴項傳遞
在useEffect依賴數組中使用對象也會導致無限循環問題。
考慮下面的代碼:
const [count, setCount] = useState(0); const person = { name: "Rue", age: 17 }; //創建一個對象 useEffect(() => { // 每次增加count的值 // person的值發生了變化 setCount((count) => count + 1); }, [person]); // 依賴項數組包含一個對象作為參數 return ( <div className="App"> <p> Value of {count} </p> </div> );
控制臺的結果表明程序是無限循環的:
是什么導致了這個問題?
- 和之前一樣,React使用淺比較來檢查person的參考值是否發生了變化
- 因為person對象的引用值在每次渲染時都會改變,所以React會重新運行useEffect
- 因此,在每個更新周期中調用setCount。這意味著我們現在有了一個無限循環
如何解決這個問題
那么我們如何解決這個問題呢?
這就是usemmo
的用武之地。**當依賴關系發生變化時,這個鉤子會計算一個記憶的值。**除此之外,因為我們記住了一個變量,這確保了狀態的引用值在每次渲染期間不會改變:
// 使用usemo創建一個對象 const person = useMemo( () => ({ name: "Rue", age: 17 }), [] //沒有依賴關系,所以值不會改變 ); useEffect(() => { setCount((count) => count + 1); }, [person]);
傳遞不正確的依賴項
如果將錯誤的變量傳遞給useEffect函數,React將拋出一個錯誤。
下面是一個簡單的例子:
const [count, setCount] = useState(0); useEffect(() => { setCount((count) => count + 1); }, [count]); //注意,我們將count傳遞給了這個數組。 return ( <div className="App"> <button onClick={() => setCount((count) => count + 1)}>+</button> <p> Value of count{count} </p> </div> );
是什么導致了這個問題?
- 在上面的代碼中,我們告訴在useEffect方法中更新count的值
- 此外,注意我們也將count Hook傳遞給了它的依賴數組
- 這意味著每次count值更新時,React都會調用useEffect
- 因此,useEffect鉤子調用setCount,從而再次更新count
- 因此,React現在在一個無限循環中運行我們的函數
如何解決這個問題
要擺脫無限循環,只需像這樣使用一個空的依賴數組:
const [count, setCount] = useState(0); // 只有在組件首次掛載時才更新'count'的值 useEffect(() => { setCount((count) => count + 1); }, []);
這將告訴React在第一次渲染時運行useEffect。
結尾
盡管React Hooks是一個簡單的概念,但是在將它們整合到項目中時,仍然需要記住許多規則。這將確保您的應用程序保持穩定,優化,并在生產過程中不拋出錯誤。
此外,最近發布的Create React App CLI
也會在運行時檢測和報告無限循環錯誤。這有助于開發人員在這些問題出現在生產服務器上之前發現并解決這些問題。
原文鏈接:https://blog.csdn.net/ImagineCode/article/details/124627512
相關推薦
- 2022-03-14 如何在Git hub上快速查找合適的項目(如何在github上找到自己想要的代碼)
- 2022-02-17 H5移動端點擊出現背景藍色框的解決方案
- 2023-03-26 python命令行參數argparse模塊基本用法詳解_python
- 2022-07-19 Linux ifconfig命令配置和顯示Linux系統網卡的網絡參數
- 2023-01-31 React組件通信淺析_React
- 2022-01-26 maatwebsite/Excel 導入 iconv (): Detected an illegal
- 2023-11-11 Python測網絡連通性、能否訪問某個網絡或者端口號<網絡檢測、ping主機、測試端口>
- 2022-08-21 android實現貝塞爾曲線之波浪效果_Android
- 最近更新
-
- 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同步修改后的遠程分支