摘要:它并不是實際在內(nèi)部的工作方式,而且它只是一個提案,在未來都會有可能發(fā)生變化。這意味著,數(shù)據(jù)的存儲是獨立于組件之外的。因此,有一個訣竅就是你需要思考作為一組需要一個匹配一致的指針去管理的數(shù)組染陌譯。
原文地址:https://medium.com/@ryardley/...
譯文:染陌 (Github)
譯文地址:https://github.com/answershuto/Blog
轉(zhuǎn)載請著名出處
我是一名hooks API的忠實粉絲,然而它對你的使用會有一些奇怪的約束,所以我在本文中使用一個模型來把原理展示給那些想去使用新的API卻難以理解它的規(guī)則的人。
警告:Hooks 還處于實驗階段本文提到的 Hooks API 還處于實驗階段,如果你需要的是穩(wěn)定的 React API 文檔,可以從這里找到。
解密 Hooks 的工作方式我發(fā)現(xiàn)一些同學(xué)苦苦思索新的 Hooks API 中的“魔法”,所以我打算嘗試著去解釋一下,至少從表層出發(fā),它是如何工作的。
Hooks 的規(guī)則React 核心團隊在Hooks的提案中提出了兩個在你使用Hooks的過程中必須去遵守的主要規(guī)則。
請不要在循環(huán)、條件或者嵌套函數(shù)中調(diào)用 Hooks
都有在 React 函數(shù)中才去調(diào)用 Hooks
后者我覺得是顯而易見的,你需要用函數(shù)的方式把行為與組件關(guān)聯(lián)起來才能把行為添加到組件。
然而對于前者,我認(rèn)為它會讓人產(chǎn)生困惑,因為這樣使用 API 編程似乎顯得不那么自然,但這就是我今天要套索的內(nèi)容。
Hooks 的狀態(tài)管理都是依賴數(shù)組的為了讓大家產(chǎn)生一個更清晰的模型,讓我們來看一下 Hooks 的簡單實現(xiàn)可能是什么樣子。
需要注意的是,這部分內(nèi)容只是 API 的一種可能實現(xiàn)方法,以便讀者更好地趣理解它。它并不是 API 實際在內(nèi)部的工作方式,而且它只是一個提案,在未來都會有可能發(fā)生變化。
我們應(yīng)該如何實現(xiàn)“useState()”呢?讓我們通過一個例子來理解狀態(tài)可能是如何工作的。
首先讓我們從一個組件開始:
代碼地址
/* 譯:https://github.com/answershuto */ function RenderFunctionComponent() { const [firstName, setFirstName] = useState("Rudi"); const [lastName, setLastName] = useState("Yardley"); return ( ); }
Hooks API 背后的思想是你可以將一個 setter 函數(shù)通過 Hook 函數(shù)的第二個參數(shù)返回,用該函數(shù)來控制 Hook 管理的壯體。
所以 React 能用這個做什么呢?首先讓我們解釋一下它在 React 內(nèi)部是如何工作的。在執(zhí)行上下文去渲染一個特殊組件的時候,下面這些步驟會被執(zhí)行。這意味著,數(shù)據(jù)的存儲是獨立于組件之外的。該狀態(tài)不能與其他組件共享,但是它擁有一個獨立的作用域,在該作用域需要被渲染時讀取數(shù)據(jù)。
(1)初始化創(chuàng)建兩個空數(shù)組“setters”與“state”
設(shè)置指針“cursor”為 0
(2)首次渲染首次執(zhí)行組件函數(shù)
每當(dāng) useState() 被調(diào)用時,如果它是首次渲染,它會通過 push 將一個 setter 方法(綁定了指針“cursor”位置)放進(jìn) setters 數(shù)組中,同時,也會將另一個對應(yīng)的狀態(tài)放進(jìn) state 數(shù)組中去。
(3)后續(xù)渲染每次的后續(xù)渲染都會重置指針“cursor”的位置,并會從每個數(shù)組中讀取對應(yīng)的值。
(4)處理事件每個 setter 都會有一個對應(yīng)的指針位置的引用,因此當(dāng)觸發(fā)任何 setter 調(diào)用的時候都會觸發(fā)去改變狀態(tài)數(shù)組中的對應(yīng)的值。
以及底層的實現(xiàn)這是一段示例代碼:
代碼地址
let state = []; let setters = []; let firstRun = true; let cursor = 0; function createSetter(cursor) { return function setterWithCursor(newVal) { state[cursor] = newVal; }; } /* 譯:https://github.com/answershuto */ // This is the pseudocode for the useState helper export function useState(initVal) { if (firstRun) { state.push(initVal); setters.push(createSetter(cursor)); firstRun = false; } const setter = setters[cursor]; const value = state[cursor]; cursor++; return [value, setter]; } /* 譯:https://github.com/answershuto */ // Our component code that uses hooks function RenderFunctionComponent() { const [firstName, setFirstName] = useState("Rudi"); // cursor: 0 const [lastName, setLastName] = useState("Yardley"); // cursor: 1 return (為什么說順序很重要呢?); } // This is sort of simulating Reacts rendering cycle function MyComponent() { cursor = 0; // resetting the cursor return; // render } console.log(state); // Pre-render: [] MyComponent(); console.log(state); // First-render: ["Rudi", "Yardley"] MyComponent(); console.log(state); // Subsequent-render: ["Rudi", "Yardley"] // click the "Fred" button console.log(state); // After-click: ["Fred", "Yardley"]
如果我們基于一些外部條件或是說組件的狀態(tài)去改變 Hooks 在渲染周期的順序,那會發(fā)生什么呢?
讓我們做一些 React 團隊禁止去做的事情。
代碼地址
let firstRender = true; function RenderFunctionComponent() { let initName; if(firstRender){ [initName] = useState("Rudi"); firstRender = false; } const [firstName, setFirstName] = useState(initName); const [lastName, setLastName] = useState("Yardley"); return ( ); }
我們在條件語句中調(diào)用了 useState 函數(shù),讓我們看看它對整個系統(tǒng)造成的破壞。
糟糕組件的首次渲染到此為止,我們的變量 firstName 與 lastName 依舊包含了正確的數(shù)據(jù),讓我們繼續(xù)去看一下第二次渲染會發(fā)生什么事情。
糟糕的第二次渲染現(xiàn)在 firstName 與 lastName 這兩個變量全部被設(shè)置為“Rudi”,與我們實際的存儲狀態(tài)不符。
這個例子的用法顯然是不正確的,但是它讓我們知道了為什么我們必須使用 React 團隊規(guī)定的規(guī)則去使用 Hooks。
React 團隊制定了這個規(guī)則,是因為如果不遵循這套規(guī)則去使用 Hooks API會導(dǎo)致數(shù)據(jù)有問題。思考 Hooks 維護(hù)了一些列的數(shù)組,所以你不應(yīng)該去違反這些規(guī)則
所以你現(xiàn)在應(yīng)該清除為什么你不應(yīng)該在條件語句或者循環(huán)語句中使用 Hooks 了。因為我們維護(hù)了一個指針“cursor”指向一個數(shù)組,如果你改變了 render 函數(shù)內(nèi)部的調(diào)用順序,那么這個指針“cursor”將不會匹配到正確的數(shù)據(jù),你的調(diào)用也將不會指向正確的數(shù)據(jù)或句柄。
因此,有一個訣竅就是你需要思考 Hooks 作為一組需要一個匹配一致的指針“cursor”去管理的數(shù)組(染陌譯)。如果做到了這一點,那么采用任何的寫法它都可以正常工作。
總結(jié)希望通過上述的講解,我已經(jīng)給大家建立了一個關(guān)于 Hooks 的更加清晰的思維模型,以此可以去思考新的 Hooks API 底層到底做了什么事情。請記住,它真正的價值在于能夠關(guān)注點聚集在一起,同時小心它的順序,那使用 Hooks API 會很高的回報。
Hooks 是 React 組件的一個很有用的插件,這也佐證了為何大家為何對此感到如此興奮。如果你腦海中形成了我上述的這種思維模型,把這種狀態(tài)作為一組數(shù)組的存在,那么你就會發(fā)現(xiàn)在使用中不會打破它的規(guī)則。
我希望將來再去研究一下 useEffects useEffects 方法,并嘗試將其與 React 的生命周期進(jìn)行比較。
這篇文章是一篇在線文檔,如果你想要參與貢獻(xiàn)或者有任何有誤的地方,歡迎聯(lián)系我。
你可以在 Twitter 上面 fllow 我(Rudi Yardley)或者在Github找到我。
染陌 譯:https://github.com/answershuto
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99369.html
摘要:本文翻譯自原作者如果有任何版權(quán)問題,請聯(lián)系當(dāng)你在組件中調(diào)用時,你覺得會發(fā)生什么當(dāng)然,會用這條狀態(tài)重新渲染組件并且更新匹配到的,然后返回元素。如果你之前使用過一些渲染器比如說,你可能知道在頁面中使用超過一個渲染器是沒什么問題的。 本文翻譯自:How Does setState Know What to Do?原作者:Dan Abramov 如果有任何版權(quán)問題,請聯(lián)系shuirong199...
摘要:但是,你可能已經(jīng)注意到,當(dāng)你試圖通過指定依賴數(shù)組來優(yōu)化時,可能會遇到帶有過時閉包的錯誤。這是否意味著閉包是問題所在我不這么認(rèn)為。到目前為止,我所看到的所有情況下,過時的閉包問題都是由于錯誤地假設(shè)函數(shù)不更改或總是相同而發(fā)生的。 原文鏈接:https://overreacted.io/how-ar... 在很長一段時間內(nèi),標(biāo)準(zhǔn)答案是class components提供更多的特性(像sta...
摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時一運維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大的...
摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時一運維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大的...
閱讀 669·2021-10-09 09:41
閱讀 652·2019-08-30 15:53
閱讀 1081·2019-08-30 15:53
閱讀 1215·2019-08-30 11:01
閱讀 1572·2019-08-29 17:31
閱讀 992·2019-08-29 14:05
閱讀 1721·2019-08-29 12:49
閱讀 416·2019-08-28 18:17