I'm facing a challenge with debouncing multiple calls to a function in a React component, where each call represents an update to the number of copies for a specific file. To implement debouncing, I'm using the debounce method from the lodash library and the useCallback hook to prevent unnecessary re-renders. Here's the current code snippet:
const updateFileCopies = async (params: addReduceCopiesParams) => {
return addReduceCopiesMutation.mutateAsync(params);
}
const debouncedFileCopiesUpdate = useCallback(_debounce(updateFileCopies, 1000), []);
const addReduceCopies = async (file: OrderDocumentProps, isAdd = false) => {
/** here I find the file and update the UI state ... **/
debouncedFileCopiesUpdate({
fileId: file.id as string,
copies: newCopiesNumber
});
}
The issue arises when a user rapidly clicks the add/reduce buttons for different files. The current implementation debounces all calls, leading to only the last call for a specific file being sent to the server. Other files don't get updated.
For example, with the following sequence of calls:
addReduceCopies({ id: 1, isAdd: true })
addReduceCopies({ id: 1, isAdd: true })
addReduceCopies({ id: 1, isAdd: true })
addReduceCopies({ id: 2, isAdd: true })
addReduceCopies({ id: 2, isAdd: true })
addReduceCopies({ id: 1, isAdd: true })
Only the last call for file with id 1 gets processed, and the file with id 2 doesn't get updated.
How can I modify the existing code to implement separate debouncing for each file, ensuring that all updates are processed independently?
You can create a function that holds a
Mapof keys, and their respective debounced functions.Note: one thing to consider is that the there will be a debounced function for each key, so the internal map would keep growing even if the key doesn't appear anymore. To prevent that, as soon as the wrapped function is invoked, we also delete it's key from the Map. If the key would appear again, a new debounced function would be created and used until the wrapped function is invoked.