自定义 Hook 概述

  • 通过自定义 Hook,可以对其它 Hook 的代码进行复用

官方文档地址:​​https://react.docschina.org/docs/hooks-custom.html​

假如现在博主有这么一个需求,就是定义两个组件然后在 App 根组件当中进行使用,使用的时候分别为定义的两个组件添加监听, 移除监听:

import React, {useEffect, useState} from 'react';

function Home() {
useEffect(() => {
console.log('Home - 组件被挂载或者更新完成 -- 添加监听');
return () => {
console.log('Home - 组件即将被卸载 -- 移除监听');
}
});
return (
<div>Home</div>
)
}

function About() {
useEffect(() => {
console.log('About - 组件被挂载或者更新完成 -- 添加监听');
return () => {
console.log('About - 组件即将被卸载 -- 移除监听');
}
});
return (
<div>About</div>
)
}

export default function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={() => {
setShow(!show)
}}>切换
</button>
</div>
)
}

测试方式就是运行项目,之后,点击切换按钮即可测试,经过如上的代码可以发现出现了冗余的代码,那么就是存在问题的,那么我们是不是就可以将这些冗余的代码进行抽取一下,抽取之后的代码如下:

import React, {useEffect, useState} from 'react';

function addListener(name) {
useEffect(() => {
console.log(name, ' - 组件被挂载或者更新完成 -- 添加监听');
return () => {
console.log(name, ' - 组件即将被卸载 -- 移除监听');
}
});
}

function Home() {
addListener('Home');
return (
<div>Home</div>
)
}

function About() {
addListener('About');
return (
<div>About</div>
)
}

export default function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={() => {
setShow(!show)
}}>切换
</button>
</div>
)
}

抽取之后发现运行报错了,这里就需要回顾一下之前的知识点了,也就是 Hook 的注意点,在 React 中只有两个地方可以使用 Hook:

  • 函数式组件中
  • 自定义 Hook 中

自定义一个 Hooks

  • 只要在函数名称前面加上​​use​​, 那么就表示这个函数是一个自定义 Hook, 就表示可以在这个函数中使用其它的 Hook

好了了解了这些知识点之后,我们接下来就可以解决我们如上示例的报错了,更改代码如下:

import React, {useEffect, useState} from 'react';

function useAddListener(name) {
useEffect(() => {
console.log(name, ' - 组件被挂载或者更新完成 -- 添加监听');
return () => {
console.log(name, ' - 组件即将被卸载 -- 移除监听');
}
});
}

function Home() {
useAddListener('Home');
return (
<div>Home</div>
)
}

function About() {
useAddListener('About');
return (
<div>About</div>
)
}

export default function App() {
const [show, setShow] = useState(true);
return (
<div>
{show && <Home/>}
{show && <About/>}
<button onClick={() => {
setShow(!show)
}}>切换
</button>
</div>
)
}

如上就是关于自定义 Hook 的内容,到这里我相信如果你跟着的是博主的文档一直看到这里,应该目前是还对自定义 Hook 的印象是不太深的,因为如上的示例我们只是简简单单的打印了文字,不够贴近我们的实际开发,所以博主这里在进行编写一个贴近实际开发的真实案例来巩固一下:

import React, {createContext, useContext} from 'react';

const UserContext = createContext({});
const InfoContext = createContext({});

function Home() {
const user = useContext(UserContext);
const info = useContext(InfoContext);
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);
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
<p>{info.gender}</p>
<hr/>
</div>
)
}

export default function App() {
return (
<UserContext.Provider
value={{name: 'BNTang', age: 18}}
>
<InfoContext.Provider
value={{gender: 'man'}}
>
<Home/>
<About/>
</InfoContext.Provider>
</UserContext.Provider>
)
}

如上的示例大致就是,通过生产者生产了两个共享变量,然后在其它两个组件当中进行使用都是从 context 当中进行获取数据,这部分的数据其实都是差不多一样的,在企业开发中, 但凡需要抽取代码, 但凡被抽取的代码中用到了其它的 Hook, 那么就必须把这些代码抽取到自定义 Hook 中。

import React, {createContext, useContext} from 'react';

const UserContext = createContext({});
const InfoContext = createContext({});

function useGetContext() {
const user = useContext(UserContext);
const info = useContext(InfoContext);
return [user, info]
}

function Home() {
const [user, info] = useGetContext();
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
<p>{info.gender}</p>
<hr/>
</div>
)
}

function About() {
const [user, info] = useGetContext();
return (
<div>
<p>{user.name}</p>
<p>{user.age}</p>
<p>{info.gender}</p>
<hr/>
</div>
)
}

export default function App() {
return (
<UserContext.Provider
value={{name: 'BNTang', age: 18}}
>
<InfoContext.Provider
value={{gender: 'man'}}
>
<Home/>
<About/>
</InfoContext.Provider>
</UserContext.Provider>
)
}

到此为止,自定义 Hook 的实际使用,与巩固已经完结了,看到这里,后面更多的内容就需要自行探究了,React 这一系列的内容就大致写到这。