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)
您可以通过几个挂钩来完成此任务。首先让我们看一下用于去抖动状态的钩子:
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)
这useEffect为App您提供了一个好地方来提取您提到的您需要的服务器。可以useEffect很容易地替换为useQuery之类的东西
| 归档时间: |
|
| 查看次数: |
2600 次 |
| 最近记录: |