Reactjs 为每个类型更改执行的去抖动输入更改

Reactjs 为每个类型更改执行的去抖动输入更改,reactjs,typescript,Reactjs,Typescript,我想添加一个debounce函数,以避免为每个字符启动搜索api: export const debounce = <F extends ((...args: any) => any)>( func: F, waitFor: number, ) => { let timeout: number = 0; const debounced = (...args: any) => { clearTimeout(timeout); setT

我想添加一个debounce函数,以避免为每个字符启动搜索api:

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>;
};
export const debounce=any)>(
func:F,
等待:号码,
) => {
let timeout:number=0;
const debounced=(…参数:any)=>{
clearTimeout(超时);
setTimeout(()=>func(…args),waitFor);
};
返回取消公告为(…参数:参数)=>ReturnType;
};
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;
import React,{useCallback}来自“React”;
从“react-redux”导入{useSelector,useDispatch};
从“/taskSlice”导入{getAllTasks};
从“../../api/tasks/index”导入{ReturnedTask}”;
从“@material ui/core/TextField”导入TextField;
从“@material ui/lab/Autocomplete”导入自动完成;
从“../../app/rootReducer”导入{AppState}”;
从“./../app/utils”导入{debounce}”;
const SearchTask=()=>{
const dispatch=usedpatch();
const[open,setOpen]=React.useState(false);
const debounceOnChange=useCallback(debounce(handleChange,400),[]);
const{tasks,userId}=useSelector((state:AppState)=>({
任务: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);
功能手柄更换(
e:React.change事件,
值:字符串,
) {
常量queryParams=[`userId=${userId}`];
if(值.长度){
console.log(值);
push(`title=${value}`);
调度(getAllTasks(queryParams));
}
}
返回(
去BounceOnChange(e,值)}
getOptionSelected={(选项,值)=>option.title==value.title}
getOptionLabel={(option)=>option.title}
选项={options}
renderInput={(参数)=>(
)}
/>
);
};
导出默认搜索任务;

组件的实际行为是为每个类型的字符启动api。我只想在一段时间后启动api。如何修复它?

正如@Jayce444在评论中提到的,上下文并没有在每次调用和函数之间保留

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);
  };
};
export const debounce=any)>(
func:F,
等待:号码,
) => {
let timeout:NodeJS.timeout;
返回(…参数:任意)=>{
clearTimeout(超时);
timeout=setTimeout(()=>func(…args),waitFor);
};
};

尽管您使用
useCallback
记忆对去Bounce函数的引用,但在实际的去Bounce函数本身中,您有
const debounced=(…)…
,这意味着每次调用该函数时都将重新创建该函数。您应该使用闭包之类的东西来保留函数调用之间的上下文,这样就不会在每次重新渲染时创建一个新的超时函数。谷歌到处寻找去Bouncing的vanilla JS实现,了解如何实现去Bouncinglooks@Jayce444谢谢你的评论。我通过更新函数解决了这个问题。