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