react hooks入門詳細教程
State Hooks
案例:
import { useState } from 'react'; function Example() { const [count, setCount] = useState(0); //count:聲明的變量;setCount:改變count值的函數;0:count的初始值 return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
useState是react自帶的一個hook函數,它的作用就是用來聲明狀態變量。useState這個函數接收的參數是我們的狀態初始值(initial state),它返回瞭一個數組,這個數組的第[0]項是當前當前的狀態值,第[1]項是可以改變狀態值的方法函數。
所以我們做的事情其實就是,聲明瞭一個狀態變量count,把它的初始值設為0,同時提供瞭一個可以更改count的函數setCount
。
當用戶點擊按鈕時,我們調用setCount函數,這個函數接收的參數是修改過的新狀態值。接下來的事情就交給react瞭,react將會重新渲染我們的Example組件,
假如一個組件有多個狀態值怎麼辦?
首先,useState是可以多次調用的
,所以我們完全可以這樣寫:
function ExampleWithManyStates() { const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); }
其次,useState接收的初始值沒有規定一定要是string/number/boolean這種簡單數據類型,它完全可以接收對象或者數組作為參數。唯一需要註意的點是,之前我們的this.setState做的是合並狀態後返回一個新狀態,而useState是直接替換老狀態後返回新狀態
。
hook,一方面它是直接用在function當中,而不是class;另一方面每一個hook都是相互獨立的,不同組件調用同一個hook也能保證各自狀態的獨立性。
react是怎麼保證多個useState的相互獨立的?
答案是,react是根據useState出現的順序來定的
。我們具體來看一下
//第一次渲染 useState(42); //將age初始化為42 useState('banana'); //將fruit初始化為banana useState([{ text: 'Learn Hooks' }]); //... //第二次渲染 useState(42); //讀取狀態變量age的值(這時候傳的參數42直接被忽略) useState('banana'); //讀取狀態變量fruit的值(這時候傳的參數banana直接被忽略) useState([{ text: 'Learn Hooks' }]); //...
react規定我們必須把hooks寫在函數的最外層,不能寫在ifelse等條件語句當中,來確保hooks的執行順序一致。
Effect Hooks
案例:
import { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 類似於componentDidMount 和 componentDidUpdate: useEffect(() => { // 更新文檔的標題 document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
假如不用hooks,我們會怎麼寫?
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
我們寫的有狀態組件,通常會產生很多的副作用(side effect),比如發起ajax請求獲取數據,添加一些監聽的註冊和取消註冊,手動修改dom等等。我們之前都把這些副作用的函數寫在生命周期函數鉤子裡,比如componentDidMount,componentDidUpdate和componentWillUnmount。而現在的useEffect就相當與這些聲明周期函數鉤子的集合體
。它以一抵三。
useEffect怎麼解綁一些副作用?
傳給useEffect的副作用函數返回一個新的函數即可
。這個新的函數將會在組件下一次重新渲染之後執行。
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); // 一定註意下這個順序:告訴react在下次重新渲染組件之後,同時是下次調用ChatAPI.subscribeToFriendStatus之前執行cleanup return function cleanup() { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
怎麼跳過一些不必要的副作用函數?
按照上一節的思路,每次重新渲染都要執行一遍這些副作用函數,顯然是不經濟的。怎麼跳過一些不必要的計算呢?我們隻需要給useEffect傳第二個參數即可。用第二個參數來告訴react隻有當這個參數的值發生改變時,才執行我們傳的副作用函數(第一個參數)。
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // 隻有當count的值發生變化時,才會重新執行`document.title`這一句
當我們第二個參數傳一個空數組[]時,其實就相當於隻在首次渲染的時候執行。也就是componentDidMount加componentWillUnmount的模式。不過這種用法可能帶來bug,少用。
還有哪些自帶的Effect Hooks?
useContext
useReducer
useCallback
useMemo
useRef
useImperativeMethods
useMutationEffect
useLayoutEffect
怎麼寫自定義的Effect Hooks?
為什麼要自己去寫一個Effect Hooks? 這樣我們才能把可以復用的邏輯抽離出來,變成一個個可以隨意插拔的“插銷”
,哪個組件要用來,我就插進哪個組件裡
比如我們可以把上面寫的FriendStatus組件中判斷朋友是否在線的功能抽出來,新建一個useFriendStatus的hook專門用來判斷某個id是否在線。
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; }
這時候FriendStatus組件就可以簡寫為:
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> ); }
這樣就實現瞭組件復用
。
taro hooks
在 Taro 中使用 Hooks API 很簡單,Taro 的專有 Hooks(例如 usePageScroll, useReachBottom)從 @tarojs/taro 中引入,框架自己的 Hooks (例如 useEffect, useState)從對應的框架引入。
import { usePageScroll, useReachBottom } from '@tarojs/taro' // Taro 專有 Hooks import { useState, useEffect } from 'react' // 框架 Hooks (基礎 Hooks)
到此這篇關於react hooks入門詳細教程的文章就介紹到這瞭,更多相關react hooks入門內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- None Found