Rxjs debounce в компоненте ввода реагирующего текста с использованием Subjects не выполняет пакетный ввод текста в компоненте без состояния / функциональном - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь глубже погрузиться в rxjs и обнаружил проблему, когда поле ввода, которое я пытаюсь отменить, отправляет событие при каждом нажатии клавиши, отладка содержит только выходные данные, но приводит к дереву, как:

a
as(delay - waits 200ms, then fires the rest synchronously)
asd
asdf
asdfg 
....

Тот же код работает, как и ожидалось, в компоненте класса (https://stackoverflow.com/a/44300853/1356046), но не может понять, почему он не работает с компонентами без сохранения состояния. Вот пример: https://stackblitz.com/edit/react-hzhrmf - вы можете увидетьОбновление useState запускается при каждом нажатии клавиши.

Большое спасибо.

1 Ответ

0 голосов
/ 23 октября 2019

React постоянно вызывает вашу функцию для визуализации компонента. Поэтому тема постоянно воссоздается.

Использование фабрики с useState для сохранения темы и работа с useEffect, чтобы убедиться, что подписка производится только один раз, должна решить вашу проблему.

Что-то вроде этого:

import React, { Component, useState, useEffect, useRef } from 'react';
import { render } from 'react-dom';
import { debounceTime, map, tap, distinctUntilChanged } from 'rxjs/operators';
import { fromEvent, Subject } from 'rxjs';

import './style.css';
const App = props => {
  const [queryName, setQueryName] = useState("");
  const [debouncedName, setDebouncedName] = useState("");
  const [onSearch$] = useState(()=>new Subject());
  useEffect(() => {
    const subscription = onSearch$.pipe(
      debounceTime(400),
      distinctUntilChanged(),
      tap(a => console.log(a))
    ).subscribe(setDebouncedName);
  }, [])
  const handleSearch = e => {
    setQueryName(e.target.value);
    onSearch$.next(e.target.value);
  };

  return (
    <div>
      <input
        placeholder="Search Tags"
        value={queryName}
        onChange={handleSearch}
      />
      <p>Debounced: {debouncedName}</p>
    </div>
  );
}

render(<App />, document.getElementById('root'));
...