【问题标题】:using debounce for search input in react在反应中使用去抖动搜索输入
【发布时间】:2018-05-15 22:11:52
【问题描述】:

我有一个搜索输入,可以即时进行 API 调用。我想实现去抖动以减少服务器调用的数量。

  _debouncedSearch() {
    debounce(this.props.fetchRoutes(this.state.searchText), 1000);
  }

  _updateResults(searchText) {
    this.setState({searchText});
    this._debouncedSearch();
  }

我期待debouncedSearch 每 1 秒。但它仍然是即时调用的。并抛出错误:

未捕获的类型错误:需要一个函数 去抖动时 (lodash.js?3387:10334)

未捕获的错误:引发了跨域错误。 React 无法访问开发中的实际错误对象。

我觉得这个问题必须经常被问到,但似乎没有一个解决方案对我有用。有人可以向我解释这里到底是什么问题吗?我认为去抖动只是一个 setTimeOut。

谢谢

【问题讨论】:

  • debounce 需要一个函数作为参数,你的 this.props.fetchRoutes(this.state.searchText) 可能返回 void 或不是函数的东西,尝试反跳函数。使用() =>this.props.fetchRoutes(this.state.searchText)function() { this.props.fetchRoutes(this.state.searchText) } : debounce 不仅仅是一个 setTimeout
  • 只是给其他人的说明,如果你在你的渲染方法中定义了一个去抖动函数,它会在每次渲染时重新创建,使去抖动无效。将其包装在 useMemo 中。 dmitripavlutin.com/react-throttle-debounce

标签: javascript reactjs lodash debounce


【解决方案1】:

最近发现这个问题很有帮助。这是我的优化解决方案:

const [searchTerm, setSearchTerm] = useState("");
const [result, setResult] = useState([]);

async function fetchData(searchTerm: string) {
  const { data } = await client.query(searchTerm);
  setResult(data);
}

const debounceLoadData = useMemo(() => debounce(fetchData, 700), []);

useEffect(() => {
  window.addEventListener("keydown", debounceLoadData(searchTerm));
  return () => {
    window.removeEventListener("keydown", debounceLoadData(searchTerm));
  };
}, [searchTerm]);

这只会在用户停止输入 700 毫秒后调用一次fetchData() 函数。然后我使用useMemo 缓存每个结果。如果用户多次搜索相同的值,它将返回缓存的值,并且不会调用fetchData() 函数。

【讨论】:

    【解决方案2】:
    constructor(props) {
        super(props);
        this.state = {
          searchText: '',
        };
        this._debouncedSearch = debounce(
          () => this.props.fetchRoutes(this.state.searchText),
          1000
        );
      }
    
      _updateResults(searchText) {
        this.setState({searchText});
        this._debouncedSearch();
      }
    

    这是完整的代码,以防有人需要!

    【讨论】:

      【解决方案3】:

      _.debounce 已经是一个执行的函数(函数返回函数)。那么_debouncedSearch 应该是类的属性,而不是方法:

        _debouncedSearch=  debounce(() => this.props.fetchRoutes(this.state.searchText), 1000);
      

      而不是:

        _debouncedSearch() {
          debounce(this.props.fetchRoutes(this.state.searchText), 1000);
        }
      

      另外,请注意,_.debounce 的第一个参数是一个函数 (() => this.props.fetchRoutes...),而不是直接this.props.fetchRoutes...

      【讨论】:

      • 不确定这是否相关。这是一些加载程序问题吗? ./src/components/home/Layout.js 模块构建失败:SyntaxError:缺少类属性转换。 29 | } 30 | > 31 | _debouncedSearch = debounce( | ^ 32 | () => this.props.fetchRoutes(this.state.searchText), 33 | 1000 34 | );
      • 顺便说一句,如果您使用的是 babel 插件,我的语法是正确的:class properties transform。但是,你没有使用它,这就是你得到 Missing class properties transform.... 的原因我建议配置你的 babel 以添加该插件并摆脱 constructor
      猜你喜欢
      • 2019-03-01
      • 2020-03-19
      • 2021-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-17
      相关资源
      最近更新 更多