摘要:粟例說明一下獲取子組件或者節(jié)點的句柄指向已掛載到上的文本輸入元素本質(zhì)上,就像是可以在其屬性中保存一個可變值的盒子。粟例說明一下渲染周期之間的共享數(shù)據(jù)的存儲上述使用聲明兩個副作用,第一個每隔一秒對加,因為只需執(zhí)行一次,所以每二個參為空數(shù)組。
想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!
React 新特性講解及實例(一)
React 新特性 Hooks 講解及實例(二)
React 新特性 Hooks 講解及實例(三)
使用 Ref Hooks類組件中使用 Ref 一般有:
String Ref
Callback Ref
CreateRef
上述在函數(shù)組件中沒有辦法使用它們,取而代之的是 useRef Hooks。
useRef 主要有兩個使用場景:
獲取子組件或者 DOM 節(jié)點的句柄
渲染周期之間的共享數(shù)據(jù)的存儲
大家可能會想到 state 也可跨越渲染周期保存,但是 state 的賦值會觸發(fā)重渲染,但是 ref 不會,從這點看 ref 更像是類屬性中的普通成員。
粟例說明一下:獲取子組件或者 DOM 節(jié)點的句柄
function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // `current` 指向已掛載到 DOM 上的文本輸入元素 inputEl.current.focus(); }; return ( <> > ); }
本質(zhì)上,useRef 就像是可以在其 .current 屬性中保存一個可變值的“盒子”。
粟例說明一下:渲染周期之間的共享數(shù)據(jù)的存儲
function App (props) { const [count, setCount] = useState(0); let it useEffect(() => { it = setInterval(() => { setCount(count => count + 1) }, 1000) } , []) useEffect(() => { if (count >= 5) { clearInterval(it) } }) return () }{count}
上述使用 useEffect 聲明兩個副作用,第一個每隔一秒對 count 加 1,因為只需執(zhí)行一次,所以每二個參為空數(shù)組。第二個 useEffect 判斷 count 大于等于時,停止對 count 的操作。
運(yùn)行結(jié)果:
顯示當(dāng) count 為 5 的時候并沒有停止,這是為什么呢?
因為在 clearInterval, it 這個變量已經(jīng)不是 setInterval 賦值時的那個了,每次 App 重渲染都會重置它。這時候就可以使用 useRef 來解決這個問題。
function App (props) { const [count, setCount] = useState(0); const it = useRef(null) useEffect(() => { it.current = setInterval(() => { setCount(count => count + 1) }, 1000) } , []) useEffect(() => { if (count >= 5) { clearInterval(it.current) } }) return ( ... ) }
使用 useRef 來創(chuàng)建一個 it, 當(dāng) setInterval 返回的結(jié)果賦值給 it 的 current 屬性。
運(yùn)行結(jié)果:
你應(yīng)該熟悉 ref 這一種訪問 DOM 的主要方式。如果你將 ref 對象以 形式傳入組件,則無論該節(jié)點如何改變,React 都會將 ref 對象的 .current 屬性設(shè)置為相應(yīng)的 DOM 節(jié)點。
然而,useRef() 比 ref 屬性更有用。它可以很方便地保存任何可變值,其類似于在 class 中使用實例字段的方式。
這是因為它創(chuàng)建的是一個普通 Javascript 對象。而 useRef() 和自建一個 {current: ...} 對象的唯一區(qū)別是,useRef 會在每次渲染時返回同一個 ref 對象。
請記住,當(dāng) ref 對象內(nèi)容發(fā)生變化時,useRef 并不會通知你。變更 .current 屬性不會引發(fā)組件重新渲染。如果想要在 React 綁定或解綁 DOM 節(jié)點的 ref 時運(yùn)行某些代碼,則需要使用回調(diào) ref 來實現(xiàn)。自定義 Hook
前面三篇,我們講到優(yōu)化類組件的三大問題:
方便復(fù)用狀態(tài)邏輯
副作用的關(guān)注點分離
函數(shù)組件無 this 問題
對于組件的復(fù)用狀態(tài)沒怎么說明,現(xiàn)在使用自定義 Hook 來說明一下。
首先我們把上面的例子用到 count 的邏輯的用自定義 Hook 封裝起來:
function useCount(defaultCount) { const [count, setCount] = useState(defaultCount); const it = useRef() useEffect(() => { it.current = setInterval(() => { setCount(count => count + 1) }, 1000) } , []) useEffect(() => { if (count >= 5) { clearInterval(it.current) } }) return [count, setCount] } function App (props) { const [count, setCount] = useCount(0); return () }{count}
運(yùn)行效果:
可以看出運(yùn)行效果跟上面是一樣的。
定義 Hook 是一個函數(shù),其名稱以 “use” 開頭,函數(shù)內(nèi)部可以調(diào)用其他的 Hook。我們在函數(shù)自定義寫法上似乎和編寫函數(shù)組件沒有區(qū)別,確實自定義組件與函數(shù)組件的最大區(qū)別就是輸入與輸出的區(qū)別。
再來一個特別的 Hook 加深一下映像。在上述代碼不變的條件下,我們在加一個自定義 Hook 內(nèi)容如下:
function useCounter(count) { return ({count}
) }
在 App 組件調(diào)用:
function App (props) { const [count, setCount] = useCount(0); const Counter = useCounter(count) return ({Counter}) }
運(yùn)行效果:
我們自定義 useCounter Hook返回的是一個 JSX,運(yùn)行效果是一樣的,所以 Hook 是可以返回 JSX 來參與渲染的,更說明 Hook 與函數(shù)組件的相似性。
使用 Hook 的法則 只在最頂層使用 Hook不要在循環(huán),條件或嵌套中調(diào)用 Hook,確??偸窃谀愕?React 函數(shù)的最頂層調(diào)用他們。遵守這條規(guī)則,你就能確保 Hook 在每一次渲染中都按照同樣的順序被調(diào)用。這上 React 能夠在多次的 useState 和 useEffect 調(diào)用之間保持 hook 狀態(tài)的正確。
只在 React 函數(shù)中調(diào)用 Hook不要在普通的 JavaScript 函數(shù)中調(diào)用 Hook, 你可以:
在 React 的函數(shù)組件中調(diào)用 Hook
在自定義 Hook 中調(diào)用其它 Hook
Hooks 常見問題以下主要說明幾個典型的問題,當(dāng)然這在官網(wǎng)上都有說明。
生命周期方法要如何對應(yīng)到 Hook?constructor:函數(shù)組件不需要構(gòu)造函數(shù)。你可以通過調(diào)用 useState 來初始化 state。如果計算的代價比較昂貴,你可以傳一個函數(shù)給 useState。
getDerivedStateFromProps:改為 在渲染時 安排一次更新
shouldComponentUpdate:詳見官網(wǎng).
render:這是函數(shù)組件體本身。
componentDidMount, componentDidUpdate, componentWillUnmount:useEffect Hook 可以表達(dá)所有這些(包括 不那么 常見 的場景)的組合。
componentDidCatch and getDerivedStateFromError:目前還沒有這些方法的 Hook 等價寫法,但很快會加上。
如何強(qiáng)制更新一個 Hooks 組件如果前后兩次的值相同,useState 和 useReducer Hook 都會放棄更新。原地修改 state 并調(diào)用 setState 不會引起重新渲染。
通常,你不應(yīng)該在 React 中修改本地 state。然而,作為一條出路,你可以用一個增長的計數(shù)器來在 state 沒變的時候依然強(qiáng)制一次重新渲染:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0); function handleClick() { forceUpdate(); }
可能的話盡量避免這種模式。
交流干貨系列文章匯總?cè)缦?,覺得不錯點個Star,歡迎 加群 互相學(xué)習(xí)。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術(shù)保持學(xué)習(xí)愛好者。我會經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!
關(guān)注公眾號,后臺回復(fù)福利,即可看到福利,你懂的。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105587.html
摘要:來個使用類形式的例子以上就不說解釋了,第一篇已經(jīng)講過了,接著將改成用的形式接著使用形式接收一個對象的返回值并返回該的當(dāng)前值。如果的返回值是函數(shù)的話,那么就可以簡寫成的方式,只是簡寫而已,實際并沒有區(qū)別。 本文是 React 系列的第三篇 React 新特性講解及實例(一) React 新特性 Hooks 講解及實例(二) 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著...
摘要:還可以返回另一個回調(diào)函數(shù),這個函數(shù)的執(zhí)行時機(jī)很重要。對于第二個我們可以通過返回一個回調(diào)函數(shù)來注銷事件的注冊?;卣{(diào)函數(shù)在視圖被銷毀之前觸發(fā),銷毀的原因有兩種重新渲染和組件卸載。 本文是 React 系列的第二篇 React 新特性講解及實例(一) 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 什么是 Hooks Hook 是 React 16.8 的新增特性。它可...
摘要:返回元素的是將新的與原始元素的淺層合并后的結(jié)果。生命周期方法要如何對應(yīng)到函數(shù)組件不需要構(gòu)造函數(shù)。除此之外,可以認(rèn)為的設(shè)計在某些方面更加高效避免了需要的額外開支,像是創(chuàng)建類實例和在構(gòu)造函數(shù)中綁定事件處理器的成本。 React系列 React系列 --- 簡單模擬語法(一)React系列 --- Jsx, 合成事件與Refs(二)React系列 --- virtualdom diff算法實...
摘要:第一次了解這項特性的時候,真的有一種豁然開朗,發(fā)現(xiàn)新大陸的感覺。在絕大多數(shù)情況下,是更好的選擇。唯一例外的就是需要根據(jù)新的來進(jìn)行操作的場景。會保證在頁面渲染前執(zhí)行,也就是說頁面渲染出來的是最終的效果。上面條規(guī)則都是為了保證調(diào)用順序的穩(wěn)定性。 歡迎關(guān)注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、...
摘要:接收一個屬性,這個組件會讓后代組件統(tǒng)一提供這個變量值。因此對于同一個對象而言,一定是后代元素。解決方法就是把內(nèi)聯(lián)函數(shù)提取出來,如下講了這么多,我們還沒有講到其實我們已經(jīng)講完了的工作原理了。 本節(jié)主要講解以下幾個新的特性: Context ContextType lazy Suspense 錯誤邊界(Error boundaries) memo 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博...
閱讀 2570·2021-09-02 15:40
閱讀 1575·2019-08-30 15:54
閱讀 1088·2019-08-30 12:48
閱讀 3409·2019-08-29 17:23
閱讀 1056·2019-08-28 18:04
閱讀 3673·2019-08-26 13:54
閱讀 614·2019-08-26 11:40
閱讀 2404·2019-08-26 10:15