1.什么是自定義 Hook?
通過(guò)自定義 Hook,可以對(duì)其它Hook的代碼進(jìn)行復(fù)用
官方文檔地址: https://react.docschina.org/docs/hooks-custom.html
注意點(diǎn): 在React中只有兩個(gè)地方可以使用Hook
- 函數(shù)式組件中
- 自定義Hook中
如何自定義一個(gè)Hooks
只要在函數(shù)名稱(chēng)前面加上use, 那么就表示這個(gè)函數(shù)是一個(gè)自定義Hook, 就表示可以在這個(gè)函數(shù)中使用其它的Hook
import React, {useEffect, useState} from 'react';
function Home() {
useEffect(()=>{
console.log('Home - 組件被掛載或者更新完成 -- 添加監(jiān)聽(tīng)');
return ()=>{
console.log('Home - 組件即將被卸載 -- 移出監(jiān)聽(tīng)');
}
});
return (
<div>Home</div>
)
}
function About() {
useEffect(()=>{
console.log('About - 組件被掛載或者更新完成 -- 添加監(jiān)聽(tīng)');
return ()=>{
console.log('About - 組件即將被卸載 -- 移出監(jiān)聽(tīng)');
}
});
return (
<div>About</div>
)
}
function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={()=>{setShow(!show)}}>切換</button>
</div>
)
}
export default App;
點(diǎn)擊按鈕.png
清空控制臺(tái)再次點(diǎn)擊按鈕.png
但是不難發(fā)現(xiàn),其實(shí)兩個(gè)組件的useEffect里頭的方法高度相似,容易造成代碼冗余巍膘,這個(gè)時(shí)候我們可以將方法抽取出來(lái),嘗試一下吧!
import React, {useEffect, useState} from 'react';
import './app.css'
function addListenr(name) {
useEffect(()=>{
console.log(name, ' - 組件被掛載或者更新完成 -- 添加監(jiān)聽(tīng)');
return ()=>{
console.log(name, ' - 組件即將被卸載 -- 移出監(jiān)聽(tīng)');
}
});
}
function Home() {
addListenr('Home');
return (
<div>Home</div>
)
}
function About() {
addListenr('About');
return (
<div>About</div>
)
}
function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={()=>{setShow(!show)}}>切換</button>
</div>
)
}
export default App;
但是去控制發(fā)現(xiàn)會(huì)報(bào)錯(cuò)
報(bào)錯(cuò).png
但是為什么會(huì)報(bào)錯(cuò)呢唆香?
原因是useEffect屬于react-hooks,他只能在函數(shù)式組件內(nèi)使用吨艇,現(xiàn)在把它定義在外面自然會(huì)報(bào)錯(cuò)
怎么解決呢躬它?使用自定義的Hooks,通過(guò)函數(shù)命名來(lái)定義,只需將addlistener函數(shù)名改為useAddListener即可
function useAddListenr(name) {
useEffect(()=>{
console.log(name, ' - 組件被掛載或者更新完成 -- 添加監(jiān)聽(tīng)');
return ()=>{
console.log(name, ' - 組件即將被卸載 -- 移出監(jiān)聽(tīng)');
}
});
}
完整代碼[final solution]
:
import React, {useEffect, useState} from 'react';
function useAddListenr(name) {
useEffect(()=>{
console.log(name, ' - 組件被掛載或者更新完成 -- 添加監(jiān)聽(tīng)');
return ()=>{
console.log(name, ' - 組件即將被卸載 -- 移出監(jiān)聽(tīng)');
}
});
}
function Home() {
useAddListenr('Home');
return (
<div>Home</div>
)
}
function About() {
useAddListenr('About');
return (
<div>About</div>
)
}
function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={()=>{setShow(!show)}}>切換</button>
</div>
)
}
export default App;
注意點(diǎn)二:在企業(yè)開(kāi)發(fā)中, 但凡需要抽取代碼, 但凡被抽取的代碼中用到了其它的Hook, 那么就必須把這些代碼抽取到自定義Hook中
import React, {createContext, useContext} from 'react';
const UserContext = createContext({});
const InfoContext = createContext({});
function useGetContext() {
//用到了useContext的hook东涡,因此必須使用自定義hook來(lái)抽取代碼進(jìn)行優(yōu)化
const user = useContext(UserContext);
const info = useContext(InfoContext);
return [user, info]
}
function Home() {
// const user = useContext(UserContext);
// const info = useContext(InfoContext);
const [user, info] = useGetContext();
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
<p>{info.gender}</p>
<hr/>
</div>
)
}
function About() {
// const user = useContext(UserContext);
// const info = useContext(InfoContext);
const [user, info] = useGetContext();
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
<p>{info.gender}</p>
<hr/>
</div>
)
}
function App() {
return (
<UserContext.Provider value={{name:'yiya_xiaoshan', age:18}}>
<InfoContext.Provider value={{gender:'female'}}>
<Home/>
<About/>
</InfoContext.Provider>
</UserContext.Provider>
)
}
export default App;
不懼怕困難冯吓,走出舒適區(qū)真正的成長(zhǎng)總是有汗水和艱辛造就的,安逸只會(huì)讓我們慢慢失去活力
不知不覺(jué)已經(jīng)到了學(xué)習(xí)react的尾聲疮跑,小單想為自己鼓掌组贺,加油!堅(jiān)持~
小單真棒.gif