|
- /*
- * @Author: 赵伟
- * @Date: 2024-04-15 10:01:29
- * @Description: 自定义 hooks
- */
- import { FormInstance } from 'antd';
- import { debounce } from 'lodash';
- import { useCallback, useEffect, useRef, useState } from 'react';
- /**
- * 生成具有初始值的状态引用
- *
- * @param initialValue - 状态的初始值
- * @return 包含状态值、状态设置函数和可变引用对象的数组
- */
- export function useStateRef<T>(initialValue: T) {
- const [value, setValue] = useState(initialValue);
-
- const ref = useRef(value);
-
- useEffect(() => {
- ref.current = value;
- }, [value]);
-
- return [value, setValue, ref] as const;
- }
-
- /**
- * 生成一个自定义钩子,用于管理模态框的可见性状态。
- *
- * @param initialValue - 模态框的初始可见性状态。
- * @return 一个数组,包含可见性状态和打开和关闭模态框的函数。
- */
- export function useVisible(initialValue: boolean) {
- const [visible, setVisible] = useState(initialValue);
- const ref = useRef(initialValue);
-
- const open = useCallback(() => {
- setVisible(true);
- }, []);
-
- const close = useCallback(() => {
- setVisible(false);
- }, []);
-
- useEffect(() => {
- ref.current = visible;
- }, [visible]);
-
- return [visible, open, close, ref] as const;
- }
-
- type Callback<T> = (state: T) => void;
-
- /**
- * 生成一个具有回调机制的可变状态值和更新它的函数。
- *
- * @param initialValue - 初始状态值。
- * @return 一个元组,包含当前状态值和用于更新状态的函数。
- */
- export function useCallbackState<T>(initialValue: T) {
- const [state, _setState] = useState<T>(initialValue);
- const callbackQueue = useRef<Callback<T>[]>([]);
- useEffect(() => {
- callbackQueue.current.forEach((cb) => cb(state));
- callbackQueue.current = [];
- }, [state]);
- const setState = (newValue: T | ((prevState: T) => T), callback?: Callback<T>) => {
- _setState(newValue);
- if (callback && typeof callback === 'function') {
- callbackQueue.current.push(callback);
- }
- };
- return [state, setState] as const;
- }
-
- /**
- * 用于追踪 DOM 元素尺寸的 hook。
- *
- * @param initialWidth - 初始宽度。
- * @param initialHeight - 初始高度。
- * @param deps - 依赖列表。
- * @return 一个元组,包含 DOM 元素的 ref、当前宽度和当前高度。
- */
- export function useDomSize<T extends HTMLElement>(
- initialWidth: number,
- initialHeight: number,
- deps: React.DependencyList = [],
- ) {
- const domRef = useRef<T>(null);
- const [width, setWidth] = useState(initialWidth);
- const [height, setHeight] = useState(initialHeight);
-
- useEffect(() => {
- const setDomHeight = () => {
- if (domRef.current) {
- setHeight(domRef.current.offsetHeight);
- setWidth(domRef.current.offsetWidth);
- }
- };
- const debounceFunc = debounce(setDomHeight, 100);
-
- setDomHeight();
- window.addEventListener('resize', debounceFunc);
-
- return () => {
- window.removeEventListener('resize', debounceFunc);
- };
- }, [domRef, ...deps]);
-
- return [domRef, { width, height }] as const;
- }
-
- /**
- * 用于在 modal 关闭时重置 Form 表单的 hook。
- *
- * @param form - Ant Design Form 表单实例
- * @param open - modal 是否打开
- */
- export const useResetFormOnCloseModal = (form: FormInstance, open: boolean) => {
- const prevOpenRef = useRef<boolean>();
-
- useEffect(() => {
- prevOpenRef.current = open;
- }, [open]);
-
- const prevOpen = prevOpenRef.current;
-
- useEffect(() => {
- if (!open && prevOpen) {
- form.resetFields();
- }
- }, [form, prevOpen, open]);
- };
-
- /**
- * Executes the effect function when the specified condition is true.
- *
- * @param effect - The effect function to execute.
- * @param deps - The dependencies for the effect.
- * @param when - The condition to trigger the effect.
- */
- export const useEffectWhen = (effect: () => void, deps: React.DependencyList, when: boolean) => {
- const requestFns = useRef<(() => void)[]>([]);
- useEffect(() => {
- if (when) {
- effect();
- } else {
- requestFns.current.splice(0, 1, effect);
- }
- }, deps);
-
- useEffect(() => {
- if (when) {
- const fn = requestFns.current.pop();
- fn?.();
- }
- }, [when]);
- };
|