React16常用自定义Hooks封装

/* 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];
};

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值