Rx js и перехватчики состояния React, вызывающие несколько вызовов API и повторных отрисовок - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь реализовать простое поле поиска в React, которое использует Rx Js. Дизайн прост, и основной лог c того, как запросы к API выполняются, как показано ниже:


export class SeachService {
  constructor() {
    this.searchTerm = new Subject();
  }

  search(term) {
    this.searchTerm.next(term.value);
  }

  doSearch(term) {
    let promise = api.business.searchByCompany(term);

    return Observable.fromPromise(promise);
  }

  getResults() {
    return this.searchTerm
      .debounceTime(300)
      .distinctUntilChanged()
      .switchMap((term) => (term ? this.doSearch(term) : Observable.of([])))
      .map((response) => {
        return {
          details: response,
          result_hash: Date.now(),
        };
      })
      .distinctUntilChanged((a, b) => a.result_hash === b.result_hash)
      .catch((error) => {
        console.error(error);
        return Observable.of([]);
      });
  }
}

И я использую его в компоненте React как:

 useLayoutEffect(() => {
    const subscription = searchService
      .getResults()
      .subscribe((res) => setBusinessResults(res.details));
  });

Однако это приводит к множеству ajax вызовов, сделанных к API, как если бы компонент повторно отрисовывался несколько раз. Когда я использую простой console.log(res.details), я получаю ожидаемое поведение, когда вызовы выполняются только один раз и соответственно регулируются. Есть ли способ исправить это?

1 Ответ

0 голосов
/ 01 августа 2020

Здесь вы можете обрабатывать несколько вызовов API. Ваш API будет вызывать только тогда, когда ввод пользователя имеет перерыв в 2 секунды.

  /**
   * Handle Timeouts
   */
  timeouts = {
    term_name: null,
  };

  /**
   * Search Term
   *
   * @param {String} name
   */
  searchTerm = name => {
    if (this.timeouts.term_name) {
      clearTimeout(this.timeouts.term_name);
    }

    this.timeouts.term_name = setTimeout(() => {
      this.searchTerm(); // Here you can call api it will trigger only if user has a gap of 2 seconds in his input
    }, 2000);
  };
...