什么是自定义Hooks
自定义Hook是解决状态逻辑重用问题的机制,其名称以"use"开头,内部可以调用其他的Hooks。遵循的规则是,只能在函数最外层调用Hook,不能在循环、条件判断或子函数中调用。此外,自定义Hook只能在React的函数组件中被调用。
总的来说,自定义Hook是一种封装了特定逻辑的函数,方便在不同的组件中重用。自定义hooks是在react-hooks基础上的一个拓展,可以根据业务需要制定满足业务需要的hooks,更注重的是逻辑单元。通过业务场景不同,我们到底需要react-hooks做什么,怎么样把一段逻辑封装起来,做到复用,这是自定义hooks产生的初衷。
如何写一个自定义Hooks
自定义Hooks大概需要五个步骤
引入react和自己需要的hook。
创建自己的hook函数。
返回一个数组,数组中第一个内容是数据,第二是修改数据的函数。
将自己定义的hook暴露出去。
在自己的业务组件中引入并使用。
下面举个简单的例子
import { useState, useEffect } from 'react';
export default function useThrottle(callback, limit) {
const [result, setResult] = useState(null);
const [throttle, setThrottle] = useState(false);
useEffect(() => {
if (!throttle) {
setThrottle(true);
const timeoutId = setTimeout(() => {
setResult(callback());
setThrottle(false);
}, limit);
return () => {
clearTimeout(timeoutId);
};
} else {
setResult(null);
}
}, [callback, limit]);
return result;
}
这个自定义Hook接收两个参数,一个回调函数和一个限制时间间隔。它使用 useState
来存储节流状态和结果,使用 useEffect
来执行节流功能。如果节流状态为 false,就执行回调函数并设置节流状态为 true,然后使用 setTimeout
在限制时间间隔后执行回调函数的返回结果,并设置节流状态为 false。如果节流状态为 true,则返回 null。
我们来看看使用场景:
const [result, setResult] = useState(null);
const myFunction = () => {
// 执行一些操作并返回结果
return 'Hello World!';
};
const throttledFunction = useThrottle(myFunction, 1000);
setResult(throttledFunction);
代码中引入了useThrottle,传入了回调函数和一个时间限定值实现了节流。
下面是一些其他的例子
处理Http请求
import { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
function useHttpClient() {
const [error, setError] = useState(null);
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [config, setConfig] = useState({});
const fetchData = useCallback((url, config) => {
setLoading(true);
axios.get(url, config)
.then((response) => {
setData(response.data);
setError(null);
})
.catch((error) => {
setError(error);
setData(null);
})
.finally(() => {
setLoading(false);
});
}, []);
useEffect(() => {
if (error) {
alert('请求失败:' + error.message);
} else if (data) {
console.log(data);
}
})
}
管理动画状态
import { useState, useEffect } from 'react';
function useAnimationState(initialState) {
const [state, setState] = useState(initialState);
const [animating, setAnimating] = useState(false);
useEffect(() => {
if (animating) {
setState(initialState);
}
}, [animating]);
const startAnimation = (callback) => {
setAnimating(true);
setTimeout(() => {
callback();
setAnimating(false);
}, 1000);
};
return [state, startAnimation];
}
总结
自定义Hooks的注意事项
自定义hook必须以use开头,这有利于react对自定义hook的规则进行检查。
不要在循环,条件或嵌套函数中调用Hook。
不要在普通的 JavaScript 函数中调用 Hook。
只能在React函数式组件或自定义Hook中使用Hook。