摘要:使用該對象,可以跟蹤屬于組件的各種元數據位。調用你的組件這意味著它知道存儲的元數據對象。下一次渲染會發生什么需要重新渲染組件由于之前已經看過這個組件,它已經有了元數據關聯。
為了保證的可讀性,本文采用意譯而非直譯。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
我們大部分 React 類組件可以保存狀態,而函數組件不能? 并且類組件具有生命周期,而函數組件卻不能?
React 早期版本,類組件可以通過繼承PureComponent來優化一些不必要的渲染,相對于函數組件,React 官網沒有提供對應的方法來緩存函數組件以減少一些不必要的渲染,直接 16.6 出來的 React.memo函數。
React 16.8 新出來的Hook可以讓React 函數組件具有狀態,并提供類似 componentDidMount和componentDidUpdate等生命周期方法。
類被會替代嗎?Hooks不會替換類,它們只是一個你可以使用的新工具。React 團隊表示他們沒有計劃在React中棄用類,所以如果你想繼續使用它們,可以繼續用。
我能體會那種總有新東西要學的感覺有多痛苦,不會就感覺咱們總是落后一樣。Hooks 可以當作一個很好的新特性來使用。當然沒有必要用 Hook 來重構原來的代碼, React團隊也建議不要這樣做。
Go Go來看看Hooks的例子,咱們先從最熟悉的開始:函數組件。
以下 OneTimeButton 是函數組件,所做的事情就是當我們點擊的時候調用 sayHi 方法。
import React from "react"; import { render } from "react-dom"; function OneTimeButton(props) { return ( ) } function sayHi() { console.log("yo") } render(, document.querySelector("#root") )
我們想讓這個組件做的是,跟蹤它是否被點擊,如果被點擊了,禁用按鈕,就像一次性開關一樣。
但它需要一個state,因為是一個函數,它不可能有狀態(React 16.8之前),所以需要重構成類。
函數組件轉換為類組件的過程中大概有5個階段:
*否認:也許它不需要是一個類,我們可以把 state 放到其它地方。
實現: 廢話,必須把它變成一個class,不是嗎?
接受:好吧,我會改的。
努力加班重寫:首先 寫 class Thing extends React.Component,然后 實現 render等等 。
最后:添加state。
class OneTimeButton extends React.Component { state = { clicked: false } handleClick = () => { this.props.onClick(); // Ok, no more clicking. this.setState({ clicked: true }); } render() { return ( ); } }
這是相當多的代碼,組件的結構也發生了很大的變化, 我們需要多個小的功能,就需要改寫很多。
使用 Hook 輕松添加 State接下來,使用新的 useState hook向普通函數組件添加狀態:
import React, { useState } from "react" function OneTimeButton(props) { const [clicked, setClicked] = useState(false) function doClick() { props.onClick(); setClicked(true) } return ( ) }這段代碼是如何工作的
這段代碼的大部分看起來像我們一分鐘前寫的普通函數組件,除了useState。
useState是一個hook。 它的名字以“use”開頭(這是Hooks的規則之一 - 它們的名字必須以“use”開頭)。
useState hook 的參數是 state 的初始值,返回一個包含兩個元素的數組:當前state和一個用于更改state 的函數。
類組件有一個大的state對象,一個函數this.setState一次改變整個state對象。
函數組件根本沒有狀態,但useState hook允許我們在需要時添加很小的狀態塊。 因此,如果只需要一個布爾值,我們就可以創建一些狀態來保存它。
由于Hook以某種特殊方式創建這些狀態,并且在函數組件內也沒有像setState函數來更改狀態,因此 Hook 需要一個函數來更新每個狀態。 所以 useState 返回是一對對應關系:一個值,一個更新該值函數。 當然,值可以是任何東西 - 任何JS類型 - 數字,布爾值,對象,數組等。
現在,你應該有很多疑問,如:
當組件重新渲染時,每次都不會重新創建新的狀態嗎? React如何知道舊狀態是什么?
為什么hook 名稱必須以“use”開頭? 這看起來很可疑。
如果這是一個命名規則,那是否意味著我可以自定義 Hook。
如何存儲更復雜的狀態,很多場景不單單只有一個狀態值這么簡單。
Hooks 的魔力將有狀態信息存儲在看似無狀態的函數組件中,這是一個奇怪的悖論。這是第一個關于鉤子的問題,咱們必須弄清楚它們是如何工作的。
原作者得的第一個猜測是某種編譯器的在背后操眾。搜索代碼useWhatever并以某種方式用有狀態邏輯替換它。
然后再聽說了調用順序規則(它們每次必須以相同的順序調用),這讓我更加困惑。這就是它的工作原理。
React第一次渲染函數組件時,它同時會創建一個對象與之共存,該對象是該組件實例的定制對象,而不是全局對象。只要組件存在于DOM中,這個組件的對象就會一直存在。
使用該對象,React可以跟蹤屬于組件的各種元數據位。
請記住,React組件甚至函數組件都從未進行過自渲染。它們不直接返回HTML。組件依賴于React在適當的時候調用它們,它們返回的對象結構React可以轉換為DOM節點。
React有能力在調用每個組件之前做一些設置,這就是它設置這個狀態的時候。
其中做的一件事設置 Hooks 數組。 它開始是空的, 每次調用一個hook時,React 都會向該數組添加該 hook。
為什么順序很重要假設咱們有以下這個組件:
function AudioPlayer() { const [volume, setVolume] = useState(80); const [position, setPosition] = useState(0); const [isPlaying, setPlaying] = useState(false); ..... }
因為它調用useState 3次,React 會在第一次渲染時將這三個 hook 放入 Hooks 數組中。
下次渲染時,同樣的3個hooks以相同的順序被調用,所以React可以查看它的數組,并發現已經在位置0有一個useState hook ,所以React不會創建一個新狀態,而是返回現有狀態。
這就是React能夠在多個函數調用中創建和維護狀態的方式,即使變量本身每次都超出作用域。
多個useState 調用示例讓咱們更詳細地看看這是如何實現的,第一次渲染:
React 創建組件時,它還沒有調用函數。React 創建元數據對象和Hooks的空數組。假設這個對象有一個名為nextHook的屬性,它被放到索引為0的位置上,運行的第一個hook將占用位置0。
React 調用你的組件(這意味著它知道存儲hooks的元數據對象)。
調用useState,React創建一個新的狀態,將它放在hooks數組的第0位,并返回[volume,setVolume]對,并將volume 設置為其初始值80,它還將nextHook索引遞增1。
再次調用useState,React查看數組的第1位,看到它是空的,并創建一個新的狀態。 然后它將nextHook索引遞增為2,并返回[position,setPosition]。
第三次調用useState。 React看到位置2為空,同樣創建新狀態,將nextHook遞增到3,并返回[isPlaying,setPlaying]。
現在,hooks 數組中有3個hook,渲染完成。 下一次渲染會發生什么?
React需要重新渲染組件, 由于 React 之前已經看過這個組件,它已經有了元數據關聯。
React將nextHook索引重置為0,并調用組件。
調用useState,React查看索引0處的hooks數組,并發現它已經在該槽中有一個hook。,所以無需重新創建一個,它將nextHook推進到索引1并返回[volume,setVolume],其中volume仍設置為80。
再次調用useState。 這次,nextHook為1,所以React檢查數組的索引1。同樣,hook 已經存在,所以它遞增nextHook并返回[position,setPosition]。
第三次調用useState,我想你知道現在發生了什么。
就是這樣了,知道了原理,看起來也就不那么神奇了, 但它確實依賴于一些規則,所以才有使用 Hooks 規則。
Hooks 的規則自定義 hooks 函數只需要遵守規則 3 :它們的名稱必須以“use”為前綴。
例如,我們可以從AudioPlayer組件中將3個狀態提取到自己的自定義鉤子中:
function AudioPlayer() { // Extract these 3 pieces of state: const [volume, setVolume] = useState(80); const [position, setPosition] = useState(0); const [isPlaying, setPlaying] = useState(false); // < beautiful audio player goes here > }
因此,咱們可以創建一個專門處理這些狀態的新函數,并使用一些額外的方法返回一個對象,以便更容易啟動和停止播放,例如:
function usePlayerState(lengthOfClip) { const [volume, setVolume] = useState(80); const [position, setPosition] = useState(0); const [isPlaying, setPlaying] = useState(false); const stop = () => { setPlaying(false); setPosition(0); } const start = () => { setPlaying(true); } return { volume, position, isPlaying, setVolume, setPosition, start, stop }; }
像這樣提取狀態的一個好處是可以將相關的邏輯和行為組合在一起。可以提取一組狀態和相關事件處理程序以及其他更新邏輯,這不僅可以清理組件代碼,還可以使這些邏輯和行為可重用。
另外,通過在自定義hooks中調用自定義hooks,可以將hooks組合在一起。hooks只是函數,當然,函數可以調用其他函數。
總結Hooks 提供了一種新的方式來處理React中的問題,其中的思想是很有意思且新奇的。
React團隊整合了一組很棒的文檔和一個常見問題解答,從是否需要重寫所有的類組件到鉤Hooks是否因為在渲染中創建函數而變慢? 以及兩者之間的所有東西,所以一定要看看。
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
交流干貨系列文章匯總如下,覺得不錯點個Star,歡迎 加群 互相學習。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術保持學習愛好者。我會經常分享自己所學所看的干貨,在進階的路上,共勉!
關注公眾號,后臺回復福利,即可看到福利,你懂的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109993.html
摘要:最近官方在大會上宣布內測將引入。所以我們有必要了解,以及由此引發的疑問。在進一步了解之前,我們需要先快速的了解一些基本的的用法。如何解決狀態有關的邏輯的重用和共享問題。 showImg(https://segmentfault.com/img/remote/1460000016886798?w=1500&h=750); 大家好,我是谷阿莫,今天要將的是一個...,哈哈哈,看到這個題我就...
摘要:前言樓主最近在整理的一些資料,為項目重構作準備,下午整理成了這篇文章。給傳入的是一個初始值,比如,這個按鈕的最初要顯示的是。取代了提供了一個統一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...
摘要:前言樓主最近在整理的一些資料,為項目重構作準備,下午整理成了這篇文章。給傳入的是一個初始值,比如,這個按鈕的最初要顯示的是。取代了提供了一個統一的。 showImg(https://segmentfault.com/img/bVbpUle?w=900&h=550); Hooks are a new addition in React 16.8. They let you use sta...
摘要:課程制作和案例制作都經過精心編排。對于開發者意義重大,希望對有需要的開發者有所幫助。是從提案轉為正式加入的新特性。并不需要用繼承,而是推薦用嵌套。大型項目中模塊化與功能解耦困難。從而更加易于復用和獨立測試。但使用會減少這種幾率。 showImg(https://segmentfault.com/img/bVbpNRZ?w=1920&h=1080); 講師簡介 曾任職中軟軍隊事業部,參與...
摘要:他們的應用是比較復雜的,組件樹也是非常龐大,假設有一千個組件要渲染,每個耗費一千個就是由于是單線程的,這里都在努力的干活,一旦開始,中間就不會停。 悄悄的, React v16.7 發布了。 React v16.7: No, This Is Not The One With Hooks. showImg(https://segmentfault.com/img/bVblq9L?w=97...
閱讀 2984·2023-04-26 00:23
閱讀 3399·2021-09-13 10:28
閱讀 2178·2021-08-31 14:18
閱讀 2884·2019-08-30 15:54
閱讀 1939·2019-08-30 15:43
閱讀 1276·2019-08-29 16:56
閱讀 2800·2019-08-29 14:16
閱讀 2053·2019-08-28 17:51