Hooks介紹之前沒有用hooks寫react的時(shí)候,用class類組件,state在構(gòu)造函數(shù)定義,然后是鉤子函數(shù)。 在這里,發(fā)現(xiàn)用的是函數(shù)組件,useState來(lái)定義state,useEffect來(lái)初始獲取接口數(shù)據(jù),比如查詢列表等等。使用hooks的目的是讓函數(shù)組件具備class組件的能力。
這里useState比原來(lái)的setstate感覺方便一點(diǎn)。在這里,沒有super(props),沒有this,沒有生命周期。hooks其實(shí)就是對(duì)原有React 的 API 進(jìn)行了封裝,暴露比較方便使用的鉤子。 ? 常用hook? useState 初始化和設(shè)置狀態(tài) 。會(huì)返回一個(gè)數(shù)組:一個(gè) state,一個(gè)更新 state 的函數(shù)。const [isEdit, setEdit] = useState(false);
useEffect??componentDidMount,componentDidUpdate和componentWillUnmount和結(jié)合體,所以可以監(jiān)聽useState定義值的變化 監(jiān)聽變化?。會(huì)在第一次渲染之后和每次更新之后都會(huì)執(zhí)行。 useEffect(() => {
fresh 改變,就會(huì)調(diào)用getList()。 ? import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
useEffect(async () => {
const result = await axios(
'http://localhost/api/v1/search?query=redux',
);
setData(result.data);
});
return (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
);
}
export default App;
在useEffect中,不僅會(huì)請(qǐng)求后端的數(shù)據(jù),還會(huì)通過調(diào)用setData來(lái)更新本地的狀態(tài),這樣會(huì)觸發(fā)view的更新。 useEffect在組件mount時(shí)執(zhí)行,但也會(huì)在組件更新時(shí)執(zhí)行。因?yàn)槲覀冊(cè)诿看握?qǐng)求數(shù)據(jù)之后都會(huì)設(shè)置本地的狀態(tài),所以組件會(huì)更新,因此useEffect會(huì)再次執(zhí)行,因此出現(xiàn)了無(wú)限循環(huán)的情況。我們只想在組件mount時(shí)請(qǐng)求數(shù)據(jù)。我們可以傳遞一個(gè)空數(shù)組作為useEffect的第二個(gè)參數(shù),這樣就能避免在組件更新執(zhí)行useEffect,只會(huì)在組件mount時(shí)執(zhí)行。就是圖一里面的使用方法。 useCallback??記憶作用,共有兩個(gè)參數(shù),第一個(gè)參數(shù)為一個(gè)匿名函數(shù),就是我們想要?jiǎng)?chuàng)建的函數(shù)體。第二參數(shù)為一個(gè)數(shù)組,里面的每一項(xiàng)是用來(lái)判斷是否需要重新創(chuàng)建函數(shù)體的變量,如果傳入的變量值保持不變,返回記憶結(jié)果。如果任何一項(xiàng)改變,則返回新的結(jié)果。? const submit = useCallback(() => {
validateFields((err, values) => {
if (err) {
console.log(err);
return message.info("請(qǐng)完整填寫表單");
} else {
onOk({ vmData, userId: values.userId });
}
});
}, []);
useMemo 和useCallback就是解決性能問題的殺手锏。 useCallback和useMemo的參數(shù)跟useEffect一致,他們之間最大的區(qū)別有是useEffect會(huì)用于處理副作用,而前兩個(gè)hooks不能。 useMemo和useCallback都會(huì)在組件第一次渲染的時(shí)候執(zhí)行,之后會(huì)在其依賴的變量發(fā)生改變時(shí)再次執(zhí)行;并且這兩個(gè)hooks都返回緩存的值,useMemo返回緩存的變量,useCallback返回緩存的函數(shù)。 他們的作用,就是類似生命周期中的shouldComponentUpdate,當(dāng)變量改變,去判斷是否重新渲染。 知道useCallback有什么樣的特點(diǎn),那有什么作用呢? ? 使用場(chǎng)景是:有一個(gè)父組件,其中包含子組件,子組件接收一個(gè)函數(shù)作為props;通常而言,如果父組件更新了,子組件也會(huì)執(zhí)行更新;但是大多數(shù)場(chǎng)景下,更新是沒有必要的,我們可以借助useCallback來(lái)返回函數(shù),然后把這個(gè)函數(shù)作為props傳遞給子組件;這樣,子組件就能避免不必要的更新。 不僅是上面的例子,所有依賴本地狀態(tài)或props來(lái)創(chuàng)建函數(shù),需要使用到緩存函數(shù)的地方,都是useCallback的應(yīng)用場(chǎng)景。 useContext? 定義一個(gè)全局的對(duì)象,類似 context
? useReducer?可以增強(qiáng)函數(shù)提供類似 Redux 的功能? useMemo 作用和傳入?yún)?shù)與 useCallback 一致,useCallback返回函數(shù),useDemo 返回值 ?? useRef? 獲取 ref 屬性對(duì)應(yīng)的 dom? ? 前面三個(gè)用的比較多。另外,useEffect、useMemo、useCallback都是自帶閉包的。也就是說,每一次組件的渲染,其都會(huì)捕獲當(dāng)前組件函數(shù)上下文中的狀態(tài)(state, props),所以每一次這三種hooks的執(zhí)行,反映的也都是當(dāng)前的狀態(tài),你無(wú)法使用它們來(lái)捕獲上一次的狀態(tài)。對(duì)于這種情況,我們應(yīng)該使用ref來(lái)訪問。 ? 注意
? 舉個(gè)栗子import React, { Fragment, useState, useEffect } from 'react';
import axios from 'axios';
function App() {
const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState('redux');
const [url, setUrl] = useState(
'http://localhost/api/v1/search?query=redux',
);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsError(false);
setIsLoading(true);
try {
const result = await axios(url);
setData(result.data);
} catch (error) {
setIsError(true);
}
setIsLoading(false);
};
fetchData();
}, [url]);
return (
<Fragment>
<input
type="text"
value={query}
onChange={event => setQuery(event.target.value)}
/>
<button
type="button"
onClick={() =>
setUrl(`http://localhost/api/v1/search?query=${query}`)
}
>
Search
</button>
{isError && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)}
</Fragment>
);
}
export default App;
在useEffect中,請(qǐng)求數(shù)據(jù)前將loading置為true,在請(qǐng)求完成后,將loading置為false。我們可以看到useEffect的依賴數(shù)據(jù)中并沒有添加loading,這是因?yàn)?,我們不需要再loading變更時(shí)重新調(diào)用useEffect。請(qǐng)記?。?strong>只有某個(gè)變量更新后,需要重新執(zhí)行useEffect的情況,才需要將該變量添加到useEffect的依賴數(shù)組中。 loading處理完成后,還需要處理錯(cuò)誤,這里的邏輯是一樣的,使用useState來(lái)創(chuàng)建一個(gè)新的state,然后在useEffect中特定的位置來(lái)更新這個(gè)state。由于我們使用了async/await,可以使用一個(gè)大大的try-catch。 每次useEffect執(zhí)行時(shí),將會(huì)重置error;在出現(xiàn)錯(cuò)誤的時(shí)候,將error置為true;在正常請(qǐng)求完成后,將error置為false。 ? 阿里的umi HOOKs https://hooks./zh-CN/hooks/life-cycle/use-mount
? ?這個(gè)就感覺還蠻厲害的,但是得慎用。 用不好,一堆副作用,維護(hù)很麻煩! 來(lái)源:https://www./content-4-838651.html |
|
|