消除 MUI 自动完成功能无法正常工作

ton*_*on1 6 reactjs material-ui

我正在尝试实现debouncemui 自动完成,但效果不佳。

我想在更改时向服务器发送去抖请求inputValue

我错过了什么吗?

它看起来loadData会触发每次输入更改。仅第一次加载debounce有效。

https://codesandbox.io/s/debounce-not-working-j4ixgg?file=/src/App.js

这是沙箱中的代码:

import { useState, useCallback } from "react";
import { Autocomplete, TextField } from "@mui/material";
import { debounce } from "lodash";
import topFilms from "./topFilms";

export default function App() {
  const [value, setValue] = useState(null);
  const [inputValue, setInputValue] = useState("");
  const [options, setOptions] = useState([]);

  const loadData = () => {
    // sleep(1000)
    const filteredOptions = topFilms.filter((f) =>
      f.title.includes(inputValue)
    );
    // This log statement added by Ryan Cogswell to show why it isn't working.
    console.log(
      `loadData with ${filteredOptions.length} options based on "${inputValue}"`
    );
    setOptions(filteredOptions);
  };

  const debouncedLoadData = useCallback(debounce(loadData, 1000), []);

  const handleInputChange = (e, v) => {
    setInputValue(v);
    debouncedLoadData();
  };

  const handleChange = (e, v) => {
    setValue(v);
  };

  return (
    <div className="App">
      <Autocomplete
        value={value}
        inputValue={inputValue}
        onChange={handleChange}
        onInputChange={handleInputChange}
        disablePortal
        options={options}
        getOptionLabel={(option) => option.title}
        isOptionEqualToValue={(option, value) => option.title === value.title}
        id="combo-box-demo"
        renderInput={(params) => <TextField {...params} label="Movie" />}
      />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

Smu*_*iku 4

tldr:codesandbox 链接

您可以通过几个挂钩来完成此任务。首先让我们看一下用于去抖动状态的钩子:

function useDebounce(value, delay, initialValue) {
  const [state, setState] = useState(initialValue);

  useEffect(() => {
    console.log("delaying", value);
    const timer = setTimeout(() => setState(value), delay);

    // clear timeout should the value change while already debouncing
    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return state;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码接收一个值,并稍后从钩子中返回去抖后的值。useEffect 末尾的回调可防止一堆计时器相继触发。

那么你的组件可以减少为:

export default function App() {
  const [value, setValue] = useState(null);
  const [inputValue, setInputValue] = useState("");
  const [options, setOptions] = useState([]);

  const debouncedValue = useDebounce(inputValue, 1000);

  // fetch data from server
  useEffect(() => {
    console.log("fetching", debouncedValue);
    const filteredOptions = topFilms.filter((f) =>
      f.title.includes(debouncedValue)
    );
    setOptions(filteredOptions);
  }, [debouncedValue]);

  const handleInputChange = (e, v) => {
    setInputValue(v);
  };

  const handleChange = (e, v) => {
    setValue(v);
  };

  return (
    <div className="App">
      <Autocomplete
        // props
      />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

这里的useEffect是当依赖关系debouncedValue通过react状态业务改变时运行的。在文本字段中输入内容时,您的控制台应如下所示:

delaying s
delaying sp
delaying spi
fetching spi
delaying spir
fetching spir
Run Code Online (Sandbox Code Playgroud)

useEffectApp您提供了一个好地方来提取您提到的您需要的服务器。可以useEffect很容易地替换为useQuery之类的东西