/* eslint-disable import/prefer-default-export */
import { useState, useRef, useEffect, useReducer } from 'react';
type noop = () => void;
/**
* @description 强制重渲染
*/
export const useForceUpdate = () => {
const [, forceUpdate] = useReducer(s => s + 1, 0);
return forceUpdate;
};
/*
* @description 针对多层嵌套的 state 合并更新可用
* @params defaultState 默认一层及以上的对象
*/
export const useLegacyState = <T,>(defaultState: T) => {
let [state, setState] = useState(defaultState);
const setLegacyState = (nextState: Partial<T>) => {
let newState = { ...state, ...nextState };
setState(newState);
};
return [state, setLegacyState];
};
/*
* @description 只在更新时运行的 effect
* @params callback 执行的函数
*/
export const useOnlyUpdateEffect = (callback: noop) => {
let isUpdateRef = useRef(false);
useEffect(() => {
if (isUpdateRef.current) {
callback && callback();
}
if (!isUpdateRef.current) {
isUpdateRef.current = true;
}
});
};
/**
* @description 节流
* @param fn 回调函数
* @param ms 时间
* @param deps 依赖列表
*/
export const useThrottle = (fn: noop, ms = 30, deps: any[] = []) => {
let previous = useRef(0);
let [time, setTime] = useState(ms);
useEffect(() => {
let now = Date.now();
if (now - previous.current > time) {
fn();
previous.current = now;
}
}, deps);
const cancel = () => {
setTime(0);
};
return [cancel];
};
/**
* @description 防抖
* @param fn 回调函数
* @param ms 时间
* @param deps 依赖列表
*/
export const useDebounce = (fn: noop, ms = 30, deps: any[] = []) => {
let timeout = useRef<NodeJS.Timeout>();
useEffect(() => {
if (timeout.current) {
clearTimeout(timeout.current);
}
timeout.current = setTimeout(() => {
fn();
}, ms);
}, deps);
const cancel = () => {
if (timeout.current) {
clearTimeout(timeout.current);
}
};
return [cancel];
};
/**
* @description 倒计时组件
* @param defaultText 倒计时默认文案
* @param ms 时间
*/
export const useCountDown = (defaultText = '获取验证码', ms = 1000) => {
let [countText, setCountText] = useState(defaultText);
let [isActive, setActive] = useState(false);
const startCountDown = () => {
setActive(true);
setCountText('60秒');
let timer: NodeJS.Timeout | null = setInterval(() => {
setCountText(prevCount => {
let count = window.parseInt(prevCount);
if (count - 1 < 0) {
clearInterval(timer!);
timer = null;
setActive(false);
return defaultText;
}
return `${count - 1}秒`;
});
}, ms);
return () => {
timer && clearInterval(timer);
timer = null;
};
};
return [isActive, countText, startCountDown];
};
React16常用自定义Hooks封装
最新推荐文章于 2024-08-07 08:45:40 发布