Простой счетчик не прекращает увеличиваться внутри функционального компонента с помощью ловушки useEffect. - PullRequest
0 голосов
/ 14 июня 2019

Я пытаюсь использовать rxjs внутри use-effect функционального компонента Hook.

Я считаю, что useEffect можно использовать так же, как componentDidMount и componentDidUpdate.

 const Counter = () => {
  const [state, setState] = useState({counter: 0});
  useEffect(() => {
    subscriber.subscribe((value) => {
        let { counter } = state;
        counter += value;
        setState({ counter });
    });
  });
  return (
    <div>
      <span>Counter: {state.counter}</span>
      <Crementer />
    </div>
  );

Подписчик - простой субъект rxjs

const subscriber = new BehaviorSubject(0);

Также есть компонент для увеличения / уменьшения счетчика

const Crementer = () => {
  return(
    <>
      <button onClick={() => subscriber.next(1)}>+</button>
      <button onClick={() => subscriber.next(-1)}>-</button>
    </>
  )
};

(я тоже пробовал counterService.send (1))

Проблема в том, что как только я нажимаю + или - счетчик непрерывно увеличивается или уменьшается.

Вы можете увидеть поведение здесь: https://stackblitz.com/edit/react-9auz4d

Может быть, потому что useEffect работает и при обновлении? Это, вероятно, будет работать в компоненте класса с componentDidMount ()?

1 Ответ

1 голос
/ 14 июня 2019

Крючки вызываются при каждом обновлении: https://reactjs.org/docs/hooks-effect.html#explanation-why-effects-run-on-each-update

Таким образом, вы можете сохранить возвращенную подписку из subscribe звонка, а затем сохранить его в другом useState. При каждом вызове эффекта вы просто проверяете, установлен он или нет. Кстати, вы должны также вернуть функцию разрыва из этого эффекта, так что именно там вам также понадобится подписка.

Или, в конце концов, вы можете использовать второй параметр для useEffect, чтобы запустить его только один раз ( Как вызвать функцию загрузки с React useEffect только один раз ):

useEffect(() => {
  const subscription = observable.subscribe((value) => {
    let { counter } = state;
    counter += value;
    setState({ counter });
  });

  return () => subscription.unsubscribe();
}, []);
...