Reputation: 6187
I want to add a debounce function to not launch the search api for every character:
export const debounce = <F extends ((...args: any) => any)>(
func: F,
waitFor: number,
) => {
let timeout: number = 0;
const debounced = (...args: any) => {
clearTimeout(timeout);
setTimeout(() => func(...args), waitFor);
};
return debounced as (...args: Parameters<F>) => ReturnType<F>;
};
Search.tsx:
import React, { useCallback } from "react";
import { useSelector, useDispatch } from "react-redux";
import { getAllTasks } from "./taskSlice";
import { ReturnedTask } from "../../api/tasks/index";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
import { AppState } from "../../app/rootReducer";
import { debounce } from "../../app/utils";
const SearchTask = () => {
const dispatch = useDispatch();
const [open, setOpen] = React.useState(false);
const debounceOnChange = useCallback(debounce(handleChange, 400), []);
const { tasks, userId } = useSelector((state: AppState) => ({
tasks: state.task.tasks,
userId: state.authentication.user.userId,
}));
const options = tasks.length
? tasks.map((task: ReturnedTask) => ({ title: task.title }))
: [];
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
function handleChange(
e: React.ChangeEvent<{}>,
value: string,
) {
const queryParams = [`userId=${userId}`];
if (value.length) {
console.log(value);
queryParams.push(`title=${value}`);
dispatch(getAllTasks(queryParams));
}
}
return (
<Autocomplete
style={{ width: 300 }}
open={open}
onOpen={handleOpen}
onClose={handleClose}
onInputChange={(e: React.ChangeEvent<{}>, value: string) =>
debounceOnChange(e, value)}
getOptionSelected={(option, value) => option.title === value.title}
getOptionLabel={(option) => option.title}
options={options}
renderInput={(params) => (
<TextField
{...params}
label="Search Tasks"
variant="outlined"
InputProps={{ ...params.InputProps, type: "search" }}
/>
)}
/>
);
};
export default SearchTask;
The actual behavior of the component is launching the api for every character typed. I want to launch the api only after an amount of time. How can I fix it?
Upvotes: 0
Views: 292
Reputation: 6187
As @Jayce444 mentioned in the comment, the the context was not preserved between every call and the function.
export const debounce = <F extends ((...args: any) => any)>(
func: F,
waitFor: number,
) => {
let timeout: NodeJS.Timeout;
return (...args: any) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), waitFor);
};
};
Upvotes: 1