用debounce和distinctUntilChanged

时间:2019-06-26 02:23:27

标签: reactjs material-ui autosuggest tsx react-tsx

意图:

我正在尝试实现一个理想的搜索字段,该字段在进行以下操作之前不会进行任何API调用:

  1. 去抖动时间已经达到350ms
  2. 然后直到输入字段的值发生变化。

到目前为止,我已经尝试过:

我已经使用主题来跟踪输入字段中的更改。每次输入字段发生变化并调用handleSuggestionsFetchRequested时,我都会使用Subject将新值推向searchString$.next(userInput);

然后在useEffect钩子中,我pipesearchString$debounceTime(350)一起distinctUntilChanged()。像这样:

useEffect(() => {
  searchString$
  .pipe(
    debounceTime(350),
    distinctUntilChanged(),
    switchMap(searchString =>
      ajax(`https://api.github.com/search/users?q=${searchString}`)
    ),
    map((networkResponse: any) => networkResponse.response.items)
  )
  .subscribe((suggestions: Array<User>) => setSuggestions(suggestions));
}, [searchString$]);

但是,每当userInput发生更改时,API调用仍会继续进行。

问题:

我认为问题在于,每次输入字段的值更改时,我也会同时设置状态:

const handleChange = (
  event: React.ChangeEvent<{}>,
  { newValue }: Autosuggest.ChangeEvent
) => {
  setUserInput(newValue);
};

这导致组件重新呈现并调用useEffect,最终使API一次又一次地调用。

我可能是错的。

如何复制:

  

我已经创建了一个复制问题的Sample Code Sandbox

非常感谢。

1 个答案:

答案 0 :(得分:2)

由于yurzui对我的tweet的评论,我得以找出问题的原因。

我在每个对帐单上都创建了一个新的Subject作为行:

const searchString$: Subject<string> = new Subject<string>();

就在我的组件函数中。

我将其移出,它就像一种魅力。

注意:根据yurzui的建议,不要忘记在ajax调用中捕获错误,否则Subject将会死亡。

我已经更新了代码沙箱示例,以防万一有人需要参考它。