在react的学习和工作中,经常会用到Hook,但是react官方提供的Hook不满足业务需求咋办,这个时候就要去自定义一些hook了,本篇记录一下我自己有用到的一些自定义Hook,需者自取,长期更新哟!
Hook的规则
既然我们要在react中使用自定义的Hook,那么就必须遵循react对Hook制定的规则,Hook规则总共有两条
- 只在最顶层使用 Hook
- 只在 React 函数中调用 Hook
这可不是我乱说的哦,请看文档
react官方对自定义Hook也有约束
自定义 Hook 是一个函数,其名称以 “
use” 开头,函数内部可以调用其他的 Hook
如果我们在开发中不小心写错了,没有遵循这个约束,不用担心,react也会贴心的给我们报错
useHover(鼠标悬停)
function useHover() {
const [flag, setFlag] = useState(false);
const ref = useRef(null);
const changeState = (e) => {
if(e.type === 'mouseenter') {
setFlag(true);
} else {
setFlag(false);
}
};
useEffect(() => {
let dom = ref?.current;
if(dom) {
dom.addEventListener('mouseenter', changeState);
dom.addEventListener('mouseleave', changeState);
}
return () => {
dom.removeEventListener('mouseenter', changeState);
dom.removeEventListener('mouseleave', changeState);
dom = null;
};
}, [ref]);
return [ref, flag];
};
用法
export default function HoverHook() {
const [ref, isHover] = useHover();
return (
<div ref={ref}>
{isHover ? '悬' : '没悬'}
</div>
)
}
useFirstScreen(浏览器滚动超过首屏)
function useFirstScreen() {
const [past, setPast] = useState(false);
useEffect(() => {
let windowHei = window.innerHeight;
const listenScroll = () => {
const top = Math.round(document.documentElement.scrollTop);
if(top >= windowHei && !past) setPast(true);
else if(top < windowHei && past) setPast(false);
};
const listenSize = () => {
windowHei = window.innerHeight;
listenScroll();
};
window.addEventListener('scroll', listenScroll, true);
window.addEventListener('resize', listenSize);
return () => {
window.removeEventListener('scroll', listenScroll, true);
window.removeEventListener('resize', listenSize);
}
}, [past]);
return past;
}
用法
export default function FirstScreenHook() {
const flag = useFirstScreen();
return (
<div>
{
flag ? <div>回到顶部</div> : <></>
}
</div>
)
}
useCountdown(倒计时)
import { useState, useRef, useEffect } from "react";
export default function useCountdown(totalTime = 60, wait = 1000) {
/**
* totalTime:倒计时,总时长,正整数
* wait:每次计时的延迟时间,毫秒数
*/
const [lastTime, setLastTime] = useState(totalTime);
const interval = useRef({});
useEffect(() => {
if(lastTime === 0) {
clearInterval(interval.current);
setLastTime(totalTime);
}
return () => {};
}, [lastTime]);
const start = () => {
if(lastTime === 0 || lastTime === totalTime) {
setLastTime(lt => lt -= 1);
interval.current = setInterval(() => {
setLastTime(lt => lt -= 1);
}, wait);
}
};
/**
* 第一项为当前是否在计时状态
* 第二项为当前剩余时长
* 第三项为启动计时函数
*/
return [lastTime === 0 || lastTime === totalTime, lastTime, start];
}
用法
const [flag, date, func] = useCountdown(60, 500);
<button className="count-down" onClick={() => func()}>
倒计时
{
!flag && <div className="btn-mask">{date}</div>
}
</button>