首页 > 解决方案 > 简单的计数器不会停止使用 useEffect 钩子在功能组件内部递增

问题描述

我试图在功能组件的 useEffect Hook 中使用 rxjs。

我相信 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() 的类组件中工作?

标签: reactjsrxjsreact-hooks

解决方案


每次更新都会调用挂钩: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();
}, []);

推荐阅读