轉載於免費視訊網 www.rails365.net
之前我們介紹了使用hooks的原因,在開始介紹api之前,現在我們先來整體的預覽下這些api
。
從上篇的介紹可以知道,Hook
是向後相容的,有react
開發經驗的你看起來會更順暢。
是一個快節奏的概述。如果你感到困惑,可以看下上面提到的介紹裡的動機:
詳細說明 閱讀動機以瞭解我們為何將Hooks引入React。
State Hook
看下面的例子,他是一個計數器
import { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() : setCount(count + 1)}>
Click me
</button>
</div>
);
}
複製程式碼
在這裡useState
是一個Hook
(我們將在稍後討論這意味著什麼)。可以看到,在這個函式元件裡,我們向他新增一些本地狀態。React
將在重新渲染之間保留這狀態。 useState
返回一對:當前狀態值(count
)和允許你更新狀態的函式(setCount
)。你可以從事件處理程式或其他位置呼叫此函式。這個函式類似於類中的this.setState
,但是它不會將舊狀態和新狀態合併在一起。(我們將在使用State Hook中顯示一個將useState
與this.state
進行比較的示例。)
useState
的唯一引數是初始狀態。 在上面的例子中,它是0,因為我們的計數器從零開始。請注意,與this.state
不同,此處的狀態不必是物件 - 儘管可以是任何你想要的。初始狀態引數僅在第一次渲染期間使用。
宣告多個state
你可以在一個元件中多次使用State Hook
:
function ExampleWithManyStates() {
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...
}
複製程式碼
陣列解構語法允許我們為通過呼叫useState
宣告的狀態變數賦予不同的名稱。這些名稱不是useState API
的一部分。相反,React
假定如果多次呼叫useState
,則在每次渲染期間以相同的順序執行。我們將回到為什麼這種方法有效以及何時有用。
什麼是Hook
鉤子是允許從功能元件(function component)“掛鉤”React狀態和生命週期功能的功能。鉤子在類內部不起作用 - 它們允許你在沒有類的情況下使用React
。 (我們不建議你在一夜之間重寫現有元件,但如果你願意,可以開始在新元件中使用Hook
。)
React
提供了一些像useState
這樣的內建Hook
。你還可以建立自定義Hook
以在不同元件之間重用有狀態行為。我們先來看看內建的Hooks
。
詳細說明 你可以在使用State Hook中瞭解更多資訊。
Effect Hook
你之前可能已經從React
元件執行資料提取,訂閱或手動更改DOM
。我們將這些操作稱為“副作用”(或簡稱為“效果”),因為它們會影響其他元件,並且在渲染過程中無法完成。
Effect Hook
中的useEffect
增加了在功能元件執行副作用的功能。它與React
類中的componentDidMount
,componentDidUpdate
和componentWillUnmount
具有相同的用途,但統一為單個API。(我們將在使用Effect Hook
時顯示將useEffect
與這些方法進行比較的示例。)
例如,下面的元件將在React
更新DOM
後設定文件標題:
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 類似componentDidMount 和 componentDidUpdate:
useEffect(() : {
// Update the document title using the browser 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
的更改後(你可以認為是render
之後)。
效果在元件內宣告,因此可以訪問其props
和state
。預設情況下,React
在每次渲染後執行效果 - 包括第一次渲染。 (我們將更多地討論使用effect hook與類生命週期的比較。)
Effects
還可以通過指定返回函式來清理他們。看下面的這個例子:
import { 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
一樣, 你也可以在元件中使用多個效果:
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);
}
// ...
}
複製程式碼
Hooks
允許你通過哪些部分相關(例如新增和刪除訂閱)來組織元件中的副作用,而不是基於生命週期方法強制拆分。
詳細說明 你可以在使用Effect Hook中瞭解更多資訊。
Hooks
的規則
鉤子是JavaScript
函式,但它們強加了兩個額外的規則:
- 只能在頂層呼叫
Hooks
。不要在迴圈,條件或巢狀函式中呼叫Hook
- 僅從
React
功能元件呼叫Hooks
。 不要從常規JavaScript
函式中呼叫Hook
。 (還有另一個有效的地方叫Hooks
- 你自己的定製Hooks
。我們馬上就會了解它們。)
詳細說明 你可以在Rules Hook中瞭解更多資訊。
Custom Hooks
有時,我們希望在元件之間重用一些有狀態邏輯的部分。傳統上,這個問題有兩個流行的解決方案:高階元件和渲染道具。Custom Hooks
允許你執行這樣的操作,並且無需向樹中新增更多元件。在上面我們介紹了一個呼叫useState
和useEffect Hooks
的FriendStatus
元件來訂閱朋友的線上狀態。假設我們還希望在另一個元件中重用此訂閱邏輯。
首先,我們將這個邏輯提取到一個名為useFriendStatus
的自定義Hook
中:
import { 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>
);
}
複製程式碼
這些元件的狀態是完全獨立的。鉤子是重用有狀態邏輯的一種方式,而不是狀態本身。 事實上,每次呼叫Hook
都有一個完全隔離的狀態 - 所以你甚至可以在一個元件中使用相同的自定義Hook
兩次。
custom hook
更像是一種約定而非功能。如果函式的名稱以use
開頭並且它呼叫其他Hook
,我們說它是一個Custom Hook
。useSomething
命名約定是linter
外掛如何使用Hooks
在程式碼中查詢錯誤的。
詳細說明 你可以在Writing Custom Hooks中瞭解更多資訊。
Other Hooks
你可能會發現一些不太常用的內建Hook
很有用。例如,useContext允許訂閱React
上下文而不引入巢狀:
function Example() {
const locale = useContext(LocaleContext);
const theme = useContext(ThemeContext);
// ...
}
複製程式碼
useReducer允許使用reducer
管理複雜元件的本地狀態:
function Todos() {
const [todos, dispatch] = useReducer(todosReducer);
// ...
}
複製程式碼
詳細說明 你可以在 Hooks API Reference.中瞭解更多資訊。
下一章節state
請前往此處