一、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 唯一的參數就是初始 state。在上面的例子中,我們的計數器是從零開始的,所以初始 state 就是 0。值得注意的是,不同於 this.state,這里的 state 不一定要是一個對象 —— 如果你有需要,它也可以是。這個初始 state 參數只有在第一次渲染時會被用到。
二、聲明多個 state 變量
function ExampleWithManyStates() { // 聲明多個 state 變量! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... }
三、Effect Hook
你之前可能已經在 React 組件中執行過數據獲取、訂閱或者手動修改過 DOM。我們統一把這些操作稱為“副作用”,或者簡稱為“作用”。
useEffect 就是一個 Effect Hook,給函數組件增加了操作副作用的能力。它跟 class 組件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不過被合並成了一個 API。(我們會在使用 Effect Hook 里展示對比 useEffect 和這些方法的例子。)
四、
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 會在每次渲染后調用副作用函數 —— 包括第一次渲染的時候。(我們會在使用 Effect Hook 中跟 class 組件的生命周期方法做更詳細的對比。)
五、跟 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 中,我們稍后會學習到。)
七、自定義 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'; }