自定义Hook
自定义Hook: 将一些常用的, 跨越多个组件的Hook功能, 抽离出去形成一个函数, 该函数就是自定义Hook
自定义Hook: 由于其内部需要使用到Hook功能, 所以它本身也需要按照Hook的规则实现
- 函数名必须使用use开头
- 调用自定义Hook时, 应该放到最顶层
例如:
- 很多组件都需要在第一次加载完成以后获取所有用户的数据
- 我们建立一个useAllStudent.js文件, 在其中书写好获取用户数据的代码
import { useEffect, useState } from 'react';
import { fetchAllStudents } from '../service/student';
/**
* 当组件首次加载完毕以后, 获得所有的学生数据
*/
export function useAllStudents() {
const [students, setStudents] = useState([])
useEffect(() => {
(async function() {
const stus = await fetchAllStudents();
setStudents(stus);
})()
}, []) // 依赖项如果是空数组, 那么该副作用函数只会在第一次加载时运行
return students;
}
- 然后在我们真正需要使用这个封装函数的地方导入和使用,(笔者这里是在App.js中 直接使用的)
import React from 'react';
import './MyHooks/useAllStudents';
import { useAllStudents } from './MyHooks/useAllStudents';
function Test() {
const stus = useAllStudents();
const list = stus.map(stu => <li key = { stu.id }>{ stu.name }</li>);
return (
<ul>
{ list }
</ul>
)
}
export default function App(props) {
return (
<div>
<Test />
</div>
)
}
就这样我们完成了一个自定义HOOK的封装与使用, 我们也会发现, hook真的太好用了, 如果在类组件中我们想要实现同样得功能必须要在生命周期中写上请求数据的函数, 如果在多个组件中都是请求同一个接口我们也不可避免的在每个组件中的生命周期都书写一次, 当然我们也可以使用HOC高阶组件进行扩展装饰, 但是整体的代码可读性都远不如Hook, 自定义HOOK在不同组件中的使用只用调用封装好的函数就好
- 很多组件都需要在第一次加载完成以后启动一个计时器, 然后在组件销毁时卸载
- 同样我们创建一个useInterval的js文件
// useInterval.js
import { useEffect } from 'react';
/**
* 该自定义Hook用于在函数组件加载时开启计时器, 在函数组件卸载时清空掉计时器
* @param {在计时器开启期间要执行的任务} func
* @param {计时器的任务执行间隔} duration
*/
export function useInterval(func, duration) {
useEffect(() => {
let timer = setInterval(func, duration)
return () => {
// 在组件销毁时 清空计时器
clearInterval(timer);
};
}, [])
}
- 然后在App.js中调用这个封装函数
import React from 'react';
import { useInterval } from './MyHooks/useInterval';
function IntervalTest(props) {
useInterval(() => {
console.log('hello');
}, 500)
return (null);
}
export default function App(props) {
return (
<div>
<IntervalTest />
</div>
)
}
至此我们又完成了一个计时器的hook, 笔者真的觉得不要太好用这个东西, 好用到感人