useThrottledCallback time interval bug
Closed this issue · 1 comments
GH-YinXiaoMin commented
Describe the bug
time interval is not work as expected
To Reproduce
import { Button } from "@fluentui/react-components";
import { useEffect, useRef, useState } from "react";
import { useThrottledCallback } from "use-debounce";
export function AvatarPersona() {
const [deleteQueue, setDeleteQueue] = useState<number[]>([]);
const deleteLength = useRef(0);
const testHookThrottledCallback = useThrottledCallback(() => {
console.log(deleteQueue[0] + ": " + Date.now());
setDeleteQueue(orgQ => {
let curQ = orgQ.slice();
curQ.splice(0, 1);
return curQ;
});
}, 200);
useEffect(() => {
if (deleteQueue?.length > 0) {
testHookThrottledCallback();
}
}, [deleteQueue])
return (<>
<Button onClick={() => {
for (let i = 0; i < 10; i++) {
setDeleteQueue((orgQueue) => {
let curQ = orgQueue.slice();
curQ.push(i);
return curQ;
});
deleteLength.current++;
}
}}>def</Button>
</>);
}
Expected behavior
The last three digits of each timestamp should be incremented by 200 in turn.
use-debounce version:^10.0.3
xnimorz commented
Hello @GH-YinXiaoMin
Thank you for opening the issue.
Please, see the documentation of useThrottledCallback
. The case which you describes requires leading
param to be set to false
, while the default value is true
.
You can play with that param on sandbox I prepared:
https://codesandbox.io/p/sandbox/t84932?file=%2Fsrc%2Findex.js%3A28%2C8
import { useEffect, useRef, useState } from "react";
import { useThrottledCallback } from "use-debounce";
import { createRoot } from "react-dom/client";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(<AvatarPersona />);
let time;
export function AvatarPersona() {
const [deleteQueue, setDeleteQueue] = useState([]);
const deleteLength = useRef(0);
const testHookThrottledCallback = useThrottledCallback(
() => {
const newTime = Date.now();
console.log(deleteQueue[0] + ": " + (newTime - time));
time = newTime;
setDeleteQueue((orgQ) => {
let curQ = orgQ.slice();
curQ.splice(0, 1);
return curQ;
});
},
200,
// By default, throttling uses leading = true,
// which means, the very first call is executed immediately
{ leading: false }
);
useEffect(() => {
if (deleteQueue?.length > 0) {
testHookThrottledCallback();
}
}, [deleteQueue]);
return (
<>
<button
onClick={() => {
time = Date.now();
for (let i = 0; i < 10; i++) {
setDeleteQueue((orgQueue) => {
let curQ = orgQueue.slice();
curQ.push(i);
return curQ;
});
deleteLength.current++;
}
}}
>
def
</button>
</>
);
}
In that example, usage of leading: false
results in 200ms delay between any subsequent calls
While removing leading: false
will make the opposite