摘要:在讀了一些文章后,大致是找到自己總是掉坑的原因了沒理解中的特性。通過這個示例,相信會比較容易地理解特性,并如何使用來暫時繞過它。在知道并理解這個特性后,有助于進一步熟悉了的運行機制,減少掉坑的次數(shù)。
由于剛使用 React hooks 不久,對它的脾氣還拿捏不準(zhǔn),掉了很多次“坑”;這里的 “坑” 的意思并不是說 React hooks 的設(shè)計有問題,而是我在使用的時候,因為還沒有跟上它的理念導(dǎo)致的一些問題。
在讀了一些文章后,大致是找到自己總是掉坑的原因了 —— 沒理解 React Hooks 中的 Capture Value 特性。
本文就以簡單的示例來解釋這個特性所產(chǎn)生的現(xiàn)象,對理解 Capture Value 特性做一個補充。
參考文章Using the Effect Hook : 官方的 useEffect 使用教程,用例詳實 ,附 useEffect - API文檔
精讀《useEffect 完全指南》:如果你想用好 Function Component 或者 Hooks,這篇文章幾乎是必讀的,因為沒有人能猜到什么是 Capture Value,然而不能理解這個概念,F(xiàn)unction Component 也不能用的順手。
精讀《Function VS Class 組件》 :以后在 React 中經(jīng)常使用 Class 的寫法,在 React Hooks 需要轉(zhuǎn)換成函數(shù)式編程風(fēng)格,這篇文章對比了兩種寫法上的差異;(這兩種寫法沒有好壞之分,性能差距也幾乎可以忽略,而且 React 會長期支持這兩種寫法)
1、狀態(tài)值為什么不是最新的?官方相關(guān) issue:Why am I seeing stale props or state inside my function?
“這個 effects 取的值怎么不是最新的?!”這個疑惑可以說是在使用 React Hooks 時經(jīng)常遇到的疑問。
在下列代碼中,當(dāng)你點擊按鈕 3s 后,alert 顯示的數(shù)值卻是 3s 前的 count 變量 —— 即無法獲取最新的值,獲取的值是過去某個時刻的:
import React, { useState, useCallback } from "react"; import ReactDOM from "react-dom"; function Example() { const [count, setCount] = useState(0); const handleAlertClick = useCallback(()=>{ setTimeout(() => { alert("You clicked on: " + count); }, 3000) }, [count]); return (); } const rootElement = document.getElementById("root"); ReactDOM.render(You clicked {count} times
, rootElement);
示例代碼:https://codesandbox.io/s/k5pm...
具體操作步驟:
當(dāng)我們先點擊 顯示 按鈕,在 3s 后(模擬耗時任務(wù))會出現(xiàn)彈層
在這 3s 期間快速點擊 增加 count 按鈕
3s 后看到的彈層計數(shù)仍舊為 0.
2、解釋這是官方特意設(shè)置的機制,官方原文是:This prevents bugs caused by the code assuming props and state don’t change;(強行翻譯一下,大概意思是:防止因 React 認為 props 或者 state 沒有變更而引起的 bug)
為了理解官方這么設(shè)定的意圖,將上面代碼稍微修改一下:
去掉 顯示 count 按鈕
增加一個 減少 count 的按鈕
使用 useEffect 代替 useCallback,讓每次更改 count 都會彈窗
... useEffect(()=>{ setTimeout(() => { alert("count: " + count); }, 3000) }, [count]); return (); } ...You clicked {count} times
我們先點擊一次 增加 count,然后再緊接著點擊一次 減少 count:
如果不是按照官方的機制設(shè)置,那么我們看到的兩次彈層顯示的 count 數(shù)值都是 0 —— 很明顯這不是我們想要的
還好實際情況不是這樣,會先顯示 1,然后顯示 0
總結(jié)起來,這個現(xiàn)象其實就是文章 精讀《useEffect 完全指南》 所提及的 Capture Value 特性(可以自行前往原文了解更多細節(jié))
3、擴展:如何獲取即刻的 count 變量回到原來的問題,倔強如我,我就是想要在 3s 后獲取的是此時此刻的 count 變量,而不是我 3s 前點擊時的 count 值,該怎么操作?
官方給出的解決方案是,每次改變 count 的時候,將其放在 ref 類型的變量里即可。
修改一下原來的代碼:
const countRef = useRef(null); const handleAlertClick = useCallback( () => { setTimeout(() => { alert("You clicked on: " + countRef.current); }, 3000); }, [count] ); return ();You clicked {count} times
更改過后的代碼運行后,3s 后 alert 顯示的 count 變量就是你頁面上所見到的樣子了:
ref 類型的變量通常是用來存儲 DOM 元素引用,但在 react hooks 中,它可以存放任何可變數(shù)據(jù),就好比類實例屬性一樣,具體參考 Is there something like instance variables?
這等操作,其實就是借助 ref 類型變量繞過 Capture Value 特性來達到目的。
4、總結(jié)援引文章 精讀《useEffect 完全指南》 中對 Capture Value 概念的解釋:每次 Render 的內(nèi)容都會形成一個快照并保留下來,因此當(dāng)狀態(tài)變更而 Rerender 時,就形成了 N 個 Render 狀態(tài),而每個 Render 狀態(tài)都擁有自己固定不變的 Props 與 State。
通過這個示例,相信會比較容易地理解 Capture Value 特性,并如何使用 ref 來暫時繞過它。在知道并理解這個特性后,有助于進一步熟悉了 React Hooks 的運行機制,減少掉坑的次數(shù)。
這里羅列幾篇文章,方便自檢是否掌握了這個概念:
通過 React Hooks 聲明式地使用 setInterval:文章采用循序漸進的示例來解釋問題。探索如何讓 setInterval 和 Hooks 和諧地玩耍,為什么是這種方式,以及這種方式給你帶來了什么新能力。
How to get the previous props or state?: 如何獲取變更前的 props 和 state ?官網(wǎng)提供的 useRef 來解決,也有人針對它進行了封裝(How to compare oldValues and newValues on React Hooks useEffect?)
下面的是我的公眾號二維碼圖片,歡迎關(guān)注。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/109215.html
摘要:未來可能成為官方之一。討論地址是精讀組件如果你想?yún)⑴c討論,請點擊這里,每周都有新的主題,周末或周一發(fā)布。前端精讀幫你篩選靠譜的內(nèi)容。 1. 引言 為什么要了解 Function 寫法的組件呢?因為它正在變得越來越重要。 那么 React 中 Function Component 與 Class Component 有何不同? how-are-function-components-di...
摘要:在線傳遞給的是而不是,返回值即是想要透傳的數(shù)據(jù)了。所以函數(shù)組件在每次渲染的時候如果有傳遞函數(shù)的話都會重渲染子組件。在學(xué)會使用React Hooks之前,可以先看一下相關(guān)原理學(xué)習(xí)React Hooks 前言 在 React 的世界中,有容器組件和 UI 組件之分,在 React Hooks 出現(xiàn)之前,UI 組件我們可以使用函數(shù),無狀態(tài)組件來展示 UI,而對于容器組件,函數(shù)組件就顯得無能為力,我...
摘要:拿到的都是而不是原始值,且這個值會動態(tài)變化。精讀對于的與,筆者做一些對比。因此采取了作為優(yōu)化方案只有當(dāng)?shù)诙€依賴參數(shù)變化時才返回新引用。不需要使用等進行性能優(yōu)化,所有性能優(yōu)化都是自動的。前端精讀幫你篩選靠譜的內(nèi)容。 1. 引言 Vue 3.0 的發(fā)布引起了軒然大波,讓我們解讀下它的 function api RFC 詳細了解一下 Vue 團隊是怎么想的吧! 首先官方回答了幾個最受關(guān)注的...
摘要:但是,你可能已經(jīng)注意到,當(dāng)你試圖通過指定依賴數(shù)組來優(yōu)化時,可能會遇到帶有過時閉包的錯誤。這是否意味著閉包是問題所在我不這么認為。到目前為止,我所看到的所有情況下,過時的閉包問題都是由于錯誤地假設(shè)函數(shù)不更改或總是相同而發(fā)生的。 原文鏈接:https://overreacted.io/how-ar... 在很長一段時間內(nèi),標(biāo)準(zhǔn)答案是class components提供更多的特性(像sta...
摘要:難道還不允許設(shè)計得對新人更友好了我們先把做成就是找罵啊這怎么怪到我們頭上了事實是,即使在內(nèi)部,也顯然不是所有程序員都熟悉函數(shù)式編程的概念。 1.前言介紹 歷史React在2013年開源,在2015引入函數(shù)式組件,不過在日常開發(fā)中經(jīng)常被忽略。ReactJS Core Team 確實大部分成員都曾在推特上公開夸贊過對函數(shù)式編程 與 ML 系語言(或其特性)的優(yōu)點:Sebastian 日常提...
閱讀 798·2021-10-14 09:42
閱讀 2026·2021-09-22 15:04
閱讀 1669·2019-08-30 12:44
閱讀 2212·2019-08-29 13:29
閱讀 2789·2019-08-29 12:51
閱讀 605·2019-08-26 18:18
閱讀 777·2019-08-26 13:43
閱讀 2873·2019-08-26 13:38