fix(hooks): ensure exposed functions wrap by useCallback (#3607)

* fix(hooks): ensure exposed functions wrap by `useCallback`

* fix(hooks/use-real-shape): remove unnecessary dependency from `useCallback`
This commit is contained in:
安忆 2024-09-05 17:21:01 +08:00 committed by GitHub
parent 26d8f01e27
commit eda316ab24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 27 deletions

View File

@ -0,0 +1,7 @@
---
"@nextui-org/use-clipboard": patch
"@nextui-org/use-real-shape": patch
"@nextui-org/use-ref-state": patch
---
ensure exposed functions wrap by `useCallback`

View File

@ -1,4 +1,4 @@
import {useState} from "react";
import {useCallback, useState} from "react";
export interface UseClipboardProps {
/**
@ -18,34 +18,40 @@ export function useClipboard({timeout = 2000}: UseClipboardProps = {}) {
const [copied, setCopied] = useState(false);
const [copyTimeout, setCopyTimeout] = useState<ReturnType<typeof setTimeout> | null>(null);
const onClearTimeout = () => {
const onClearTimeout = useCallback(() => {
if (copyTimeout) {
clearTimeout(copyTimeout);
}
};
}, [copyTimeout]);
const handleCopyResult = (value: boolean) => {
onClearTimeout();
setCopyTimeout(setTimeout(() => setCopied(false), timeout));
setCopied(value);
};
const handleCopyResult = useCallback(
(value: boolean) => {
onClearTimeout();
setCopyTimeout(setTimeout(() => setCopied(false), timeout));
setCopied(value);
},
[onClearTimeout, timeout],
);
const copy = (valueToCopy: any) => {
if ("clipboard" in navigator) {
navigator.clipboard
.writeText(valueToCopy)
.then(() => handleCopyResult(true))
.catch((err) => setError(err));
} else {
setError(new Error("useClipboard: navigator.clipboard is not supported"));
}
};
const copy = useCallback(
(valueToCopy: any) => {
if ("clipboard" in navigator) {
navigator.clipboard
.writeText(valueToCopy)
.then(() => handleCopyResult(true))
.catch((err) => setError(err));
} else {
setError(new Error("useClipboard: navigator.clipboard is not supported"));
}
},
[handleCopyResult],
);
const reset = () => {
const reset = useCallback(() => {
setCopied(false);
setError(null);
onClearTimeout();
};
}, [onClearTimeout]);
return {copy, reset, error, copied};
}

View File

@ -1,4 +1,4 @@
import {RefObject, useState, useEffect} from "react";
import {RefObject, useCallback, useState, useEffect} from "react";
import {ShapeType, getRealShape} from "@nextui-org/react-utils";
export type ShapeResult = [ShapeType, () => void];
@ -8,15 +8,15 @@ export function useRealShape<T extends HTMLElement>(ref: RefObject<T | null>) {
width: 0,
height: 0,
});
const updateShape = () => {
const updateShape = useCallback(() => {
if (!ref?.current) return;
const {width, height} = getRealShape(ref.current);
setState({width, height});
};
}, []);
useEffect(() => updateShape(), [ref.current]);
useEffect(() => updateShape(), [updateShape]);
return [shape, updateShape] as ShapeResult;
}

View File

@ -1,4 +1,12 @@
import {Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState} from "react";
import {
Dispatch,
MutableRefObject,
SetStateAction,
useCallback,
useEffect,
useRef,
useState,
} from "react";
export type CurrentStateType<S> = [S, Dispatch<SetStateAction<S>>, MutableRefObject<S>];
@ -15,12 +23,12 @@ export function useRefState<S>(initialState: S | (() => S)) {
ref.current = state;
}, [state]);
const setValue = (val: SetStateAction<S>) => {
const setValue = useCallback((val: SetStateAction<S>) => {
const result = typeof val === "function" ? (val as (prevState: S) => S)(ref.current) : val;
ref.current = result;
setState(result);
};
}, []);
return [state, setValue, ref] as CurrentStateType<S>;
}