您好,登錄后才能下訂單哦!
這篇文章主要介紹了React的Hook是什么,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
這個例子用來顯示一個計數(shù)器。當(dāng)你點擊按鈕,計數(shù)器的值就會增加:
import React, { useState } from 'react'; function Example() { // 聲明一個叫 “count” 的 state 變量。 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
在這里,useState
就是一個 Hook (等下我們會講到這是什么意思)。通過在函數(shù)組件里調(diào)用它來給組件添加一些內(nèi)部 state
。React 會在重復(fù)渲染時保留這個 state
。useState
會返回一對值:當(dāng)前狀態(tài)和一個讓你更新它的函數(shù),你可以在事件處理函數(shù)中或其他一些地方調(diào)用這個函數(shù)。它類似 class
組件的 this.setState
,但是它不會把新的 state
和舊的 state
進(jìn)行合并。(我們會在使用 State Hook 里展示一個對比 useState
和 this.state
的例子)。
useState
唯一的參數(shù)就是初始 state
。在上面的例子中,我們的計數(shù)器是從零開始的,所以初始 state
就是 0
。值得注意的是,不同于 this.state
,這里的 state
不一定要是一個對象 —— 如果你有需要,它也可以是。這個初始 state
參數(shù)只有在第一次渲染時會被用到。
你可以在一個組件中多次使用 State Hook:
function ExampleWithManyStates() { // 聲明多個 state 變量! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... }
數(shù)組解構(gòu)的語法讓我們在調(diào)用 useState
時可以給 state
變量取不同的名字。當(dāng)然,這些名字并不是 useState
API 的一部分。React 假設(shè)當(dāng)你多次調(diào)用 useState
的時候,你能保證每次渲染時它們的調(diào)用順序是不變的。后面我們會再次解釋它是如何工作的以及在什么場景下使用。
Hook 是一些可以讓你在函數(shù)組件里 " 鉤入" React state
及生命周期等特性的函數(shù)。Hook 不能在 class
組件中使用 —— 這使得你不使用 class
也能使用 React。(我們不推薦把你已有的組件全部重寫,但是你可以在新組件里開始使用 Hook。)
React 內(nèi)置了一些像 useState
這樣的 Hook。你也可以創(chuàng)建你自己的 Hook 來復(fù)用不同組件之間的狀態(tài)邏輯。我們會先介紹這些內(nèi)置的 Hook。
你之前可能已經(jīng)在 React 組件中執(zhí)行過數(shù)據(jù)獲取、訂閱或者手動修改過 DOM。我們統(tǒng)一把這些操作稱為“副作用”,或者簡稱為“作用”。
useEffect
就是一個 Effect Hook,給函數(shù)組件增加了操作副作用的能力。它跟 class
組件中的 componentDidMount
、componentDidUpdate
和 componentWillUnmount
具有相同的用途,只不過被合并成了一個 API。
例如,下面這個組件在 React 更新 DOM 后會設(shè)置一個頁面標(biāo)題:
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 相當(dāng)于 componentDidMount 和 componentDidUpdate: useEffect(() => { // 使用瀏覽器的 API 更新頁面標(biāo)題 document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
當(dāng)你調(diào)用 useEffect
時,就是在告訴 React 在完成對 DOM 的更改后運(yùn)行你的“副作用”函數(shù)。由于副作用函數(shù)是在組件內(nèi)聲明的,所以它們可以訪問到組件的 props
和 state
。默認(rèn)情況下,React 會在每次渲染后調(diào)用副作用函數(shù) —— 包括第一次渲染的時候。
副作用函數(shù)還可以通過返回一個函數(shù)來指定如何“清除”副作用。例如,在下面的組件中使用副作用函數(shù)來訂閱好友的在線狀態(tài),并通過取消訂閱來進(jìn)行清除操作:
import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
在這個示例中,React 會在組件銷毀時取消對 ChatAPI
的訂閱,然后在后續(xù)渲染時重新執(zhí)行副作用函數(shù)。(如果傳給 ChatAPI
的 props.friend.id
沒有變化,你也可以告訴 React 跳過重新訂閱。)
跟 useState
一樣,你可以在組件中多次使用 useEffect
:
function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ...
通過使用 Hook,你可以把組件內(nèi)相關(guān)的副作用組織在一起(例如創(chuàng)建訂閱及取消訂閱),而不要把它們拆分到不同的生命周期函數(shù)里。
Hook 就是 JavaScript 函數(shù),但是使用它們會有兩個額外的規(guī)則:
只能在函數(shù)最外層調(diào)用 Hook。不要在循環(huán)、條件判斷或者子函數(shù)中調(diào)用。
只能在 React 的函數(shù)組件中調(diào)用 Hook。不要在其他 JavaScript 函數(shù)中調(diào)用。(還有一個地方可以調(diào)用 Hook —— 就是自定義的 Hook 中,我們稍后會學(xué)習(xí)到。)
有時候我們會想要在組件之間重用一些狀態(tài)邏輯。目前為止,有兩種主流方案來解決這個問題:高階組件和 render props
。自定義 Hook 可以讓你在不增加組件的情況下達(dá)到同樣的目的。
前面,我們介紹了一個叫 FriendStatus
的組件,它通過調(diào)用 useState
和 useEffect
的 Hook 來訂閱一個好友的在線狀態(tài)。假設(shè)我們想在另一個組件里重用這個訂閱邏輯。
首先,我們把這個邏輯抽取到一個叫做 useFriendStatus
的自定義 Hook 里:
import React, { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; }
它將 friendID
作為參數(shù),并返回該好友是否在線:
現(xiàn)在我們可以在兩個組件中使用它:
function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {props.friend.name} </li> ); }
每個組件間的 state
是完全獨立的。Hook 是一種復(fù)用狀態(tài)邏輯的方式,它不復(fù)用 state
本身。事實上 Hook 的每次調(diào)用都有一個完全獨立的 state
—— 因此你可以在單個組件中多次調(diào)用同一個自定義 Hook。
自定義 Hook 更像是一種約定而不是功能。如果函數(shù)的名字以 use
開頭并調(diào)用其他 Hook,我們就說這是一個自定義 Hook。 useSomething
的命名約定可以讓我們的 linter
插件在使用 Hook 的代碼中找到 bug。
你可以創(chuàng)建涵蓋各種場景的自定義 Hook,如表單處理、動畫、訂閱聲明、計時器,甚至可能還有更多我們沒想到的場景。我們很期待看到 React 社區(qū)會出現(xiàn)什么樣的自定義 Hook。
除此之外,還有一些使用頻率較低的但是很有用的 Hook。比如,useContext
讓你不使用組件嵌套就可以訂閱 React 的 Context。
function Example() { const locale = useContext(LocaleContext); const theme = useContext(ThemeContext); // ... }
另外 useReducer
可以讓你通過 reducer
來管理組件本地的復(fù)雜 state
。
function Todos() { const [todos, dispatch] = useReducer(todosReducer); // ...
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“React的Hook是什么”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。