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