Skip to content

Commit

Permalink
fix(hooks): ensure exposed functions wrap by useCallback (#3607)
Browse files Browse the repository at this point in the history
* fix(hooks): ensure exposed functions wrap by `useCallback`

* fix(hooks/use-real-shape): remove unnecessary dependency from `useCallback`
  • Loading branch information
AnYiEE committed Sep 5, 2024
1 parent 26d8f01 commit eda316a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 30 deletions.
7 changes: 7 additions & 0 deletions .changeset/selfish-spies-visit.md
Original file line number Diff line number Diff line change
@@ -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`
52 changes: 29 additions & 23 deletions packages/hooks/use-clipboard/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useState} from "react";
import {useCallback, useState} from "react";

export interface UseClipboardProps {
/**
Expand All @@ -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);
}
};

const handleCopyResult = (value: boolean) => {
onClearTimeout();
setCopyTimeout(setTimeout(() => setCopied(false), timeout));
setCopied(value);
};

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 reset = () => {
}, [copyTimeout]);

const handleCopyResult = useCallback(
(value: boolean) => {
onClearTimeout();
setCopyTimeout(setTimeout(() => setCopied(false), timeout));
setCopied(value);
},
[onClearTimeout, timeout],
);

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 = useCallback(() => {
setCopied(false);
setError(null);
onClearTimeout();
};
}, [onClearTimeout]);

return {copy, reset, error, copied};
}
Expand Down
8 changes: 4 additions & 4 deletions packages/hooks/use-real-shape/src/index.ts
Original file line number Diff line number Diff line change
@@ -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];
Expand All @@ -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;
}
Expand Down
14 changes: 11 additions & 3 deletions packages/hooks/use-ref-state/src/index.ts
Original file line number Diff line number Diff line change
@@ -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>];

Expand All @@ -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>;
}
Expand Down

0 comments on commit eda316a

Please sign in to comment.