延迟建议时间Material-UI AutoComplete组件

时间:2016-11-25 19:49:52

标签: reactjs material-ui

任何人都知道在提出建议之前如何延迟时间?

我一写第一封信就给了我建议,我想推迟一下, 通读文档,找不到它,也许这是不可能的?

谢谢!

2 个答案:

答案 0 :(得分:3)

你可以使用lodash的debounce()函数(基本上是一个小窗口.setTimeout技巧来限制重复调用):

import _ from 'lodash';

...

doSearch(text) {
   // Your normal handler here
}

...

// Delay autocomplete until 500 ms after use stops typing
<AutoComplete
  onUpdateInput={_.debounce((value) => doSearch(value), 500)}
  ...
/>

答案 1 :(得分:2)

传统的方法是在用户输入时使用 debouncethrottle 来延迟函数调用。它们之间的延迟行为略有不同,有关详细信息,请参阅 here。对于这个答案,我将使用 debounce 中的 lodash

另外请不要复制点赞最多的answer。这是错误的并且使用了不好的做法:

  • 它会导入整个 lodash 包,其中包含您可能不需要的无数 other methods,并且会增加您的最终 bundle size。执行此操作的 correct way 是使用此导入语法:
import debounce from 'lodash/debounce
  • 它将 debounce(handleSearch) 的结果直接传递给 onUpdateInput 道具。 debounce 是一个高阶函数,它是一个函数工厂,用于创建另一个可以延迟的函数:
const handleSearch = () => { // ... }
const handleSearchDelayed = debounce(handleSearch, 50);

handleSearchDelayed();
handleSearchDelayed();
handleSearchDelayed();

// handleSearchDelayed is called 3 times but handleSearch will only be called 1 time
// 50ms later

这意味着每次重新渲染组件时,debounce(handleSearch) 都会创建一个带有自己的延迟计时器的新函数,也就是每次用户在文本字段中键入时。这会产生意想不到的副作用,甚至使组件根本无法工作。

解决方案是在组件重新渲染时使用useCallback返回相同的延迟函数实例。以下是最小的工作示例:

import React, { useCallback, useEffect, useState } from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import TextField from "@material-ui/core/TextField";
import debounce from "lodash/debounce";
import { getOptionsAsync } from "./options";

function App() {
  const [options, setOptions] = useState([]);
  const [inputValue, setInputValue] = React.useState("");
  const getOptionsDelayed = useCallback(
    debounce((text, callback) => {
      setOptions([]);
      getOptionsAsync(text).then(callback);
    }, 200),
    []
  );

  useEffect(() => {
    getOptionsDelayed(inputValue, (filteredOptions) => {
      setOptions(filteredOptions);
    });
  }, [inputValue, getOptionsDelayed]);

  return (
    <Autocomplete
      options={options}
      getOptionLabel={(option) => option.title}
      filterOptions={(x) => x} // disable filtering on client
      loading={options.length === 0}
      onInputChange={(e, newInputValue) => setInputValue(newInputValue)}
      renderInput={(params) => <TextField {...params} label="Combo box" />}
    />
  );
}

现场演示

Edit 40811535/delay-suggestion-time-material-ui-autocomplete-component