react-autosuggest with debounce 和 distinctUntilChanged

react-autosuggest with debounce and distinctUntilChanged

意图:

我正在尝试实现一个理想的搜索字段,该字段不会进行任何 API 调用,直到:

  1. 已达到 350 毫秒的去抖时间
  2. AND 直到输入字段的值发生变化。

到目前为止我尝试过的:

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

将新值向下推到 Subject

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 调用。

我可能是错的。

如何复制:

I've created a Sample Code Sandbox that replicates the issue.

非常感谢。

感谢 yurzui on my tweet 的评论,我能够找出问题的原因。

我在每次对帐时都创建了一个新的 Subject 行:

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

就在我的组件函数中。

我把它搬出去了,效果很好。

注意:正如 yurzui 所建议的那样,不要忘记在 ajax 调用中捕获错误,否则 Subject 会死掉。

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