react hooks入門詳細教程
State Hooks
案例:
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
//count:聲明的變量;setCount:改變count值的函數(shù);0:count的初始值
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useState是react自帶的一個hook函數(shù),它的作用就是用來聲明狀態(tài)變量。useState這個函數(shù)接收的參數(shù)是我們的狀態(tài)初始值(initial state),它返回了一個數(shù)組,這個數(shù)組的第[0]項是當前當前的狀態(tài)值,第[1]項是可以改變狀態(tài)值的方法函數(shù)。
所以我們做的事情其實就是,聲明了一個狀態(tài)變量count,把它的初始值設(shè)為0,同時提供了一個可以更改count的函數(shù)setCount。
當用戶點擊按鈕時,我們調(diào)用setCount函數(shù),這個函數(shù)接收的參數(shù)是修改過的新狀態(tài)值。接下來的事情就交給react了,react將會重新渲染我們的Example組件,
假如一個組件有多個狀態(tài)值怎么辦?
首先,useState是可以多次調(diào)用的,所以我們完全可以這樣寫:
function ExampleWithManyStates() {
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
}
其次,useState接收的初始值沒有規(guī)定一定要是string/number/boolean這種簡單數(shù)據(jù)類型,它完全可以接收對象或者數(shù)組作為參數(shù)。唯一需要注意的點是,之前我們的this.setState做的是合并狀態(tài)后返回一個新狀態(tài),而useState是直接替換老狀態(tài)后返回新狀態(tài)。
hook,一方面它是直接用在function當中,而不是class;另一方面每一個hook都是相互獨立的,不同組件調(diào)用同一個hook也能保證各自狀態(tài)的獨立性。
react是怎么保證多個useState的相互獨立的?
答案是,react是根據(jù)useState出現(xiàn)的順序來定的。我們具體來看一下
//第一次渲染
useState(42); //將age初始化為42
useState('banana'); //將fruit初始化為banana
useState([{ text: 'Learn Hooks' }]); //...
//第二次渲染
useState(42); //讀取狀態(tài)變量age的值(這時候傳的參數(shù)42直接被忽略)
useState('banana'); //讀取狀態(tài)變量fruit的值(這時候傳的參數(shù)banana直接被忽略)
useState([{ text: 'Learn Hooks' }]); //...
react規(guī)定我們必須把hooks寫在函數(shù)的最外層,不能寫在ifelse等條件語句當中,來確保hooks的執(zhí)行順序一致。
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>
);
}
}
我們寫的有狀態(tài)組件,通常會產(chǎn)生很多的副作用(side effect),比如發(fā)起ajax請求獲取數(shù)據(jù),添加一些監(jiān)聽的注冊和取消注冊,手動修改dom等等。我們之前都把這些副作用的函數(shù)寫在生命周期函數(shù)鉤子里,比如componentDidMount,componentDidUpdate和componentWillUnmount。而現(xiàn)在的useEffect就相當與這些聲明周期函數(shù)鉤子的集合體。它以一抵三。
useEffect怎么解綁一些副作用?
傳給useEffect的副作用函數(shù)返回一個新的函數(shù)即可。這個新的函數(shù)將會在組件下一次重新渲染之后執(zhí)行。
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在下次重新渲染組件之后,同時是下次調(diào)用ChatAPI.subscribeToFriendStatus之前執(zhí)行cleanup
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
怎么跳過一些不必要的副作用函數(shù)?
按照上一節(jié)的思路,每次重新渲染都要執(zhí)行一遍這些副作用函數(shù),顯然是不經(jīng)濟的。怎么跳過一些不必要的計算呢?我們只需要給useEffect傳第二個參數(shù)即可。用第二個參數(shù)來告訴react只有當這個參數(shù)的值發(fā)生改變時,才執(zhí)行我們傳的副作用函數(shù)(第一個參數(shù))。
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 只有當count的值發(fā)生變化時,才會重新執(zhí)行`document.title`這一句
當我們第二個參數(shù)傳一個空數(shù)組[]時,其實就相當于只在首次渲染的時候執(zhí)行。也就是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>
);
}
這樣就實現(xiàn)了組件復用。
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 (基礎(chǔ) Hooks)
到此這篇關(guān)于react hooks入門詳細教程的文章就介紹到這了,更多相關(guān)react hooks入門內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React-router4路由監(jiān)聽的實現(xiàn)
這篇文章主要介紹了React-router4路由監(jiān)聽的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
解決react中useState狀態(tài)異步更新的問題
本文主要介紹了react中useState狀態(tài)異步更新的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07

