首页 > 解决方案 > 为什么 RxJS 间隔从最后一个值开始而不是从“0”开始?

问题描述

Reset单击按钮时,我需要将自定义计时器重置为“0 秒” 。但是当我按下Start我的计时器时,它会从最后一个值继续,而不是从“0 秒”开始。

const [time, setTime] = useState (0);
const [timerOn, setTimerOn ] = useState (false);

let observable$ = interval(1000);
    
  let subscription = observable$.subscribe(result =>{
    if (timerOn) {
      setTime(result);
    }
  });
  return () => subscription.unsubscribe();
}, [timerOn]);

return (
<div>
{!timerOn && (
        <button onClick={() => setTimerOn(true)}>Start</button>
        )}
{ time > 0 && (
    <button onClick={() => setTime(0)}>Reset</button>
    )}  

标签: reactjsrxjsobservable

解决方案


问题

让我们看一下Reset按钮:

<button onClick={() => setTime(0)}>Reset</button>

当您单击此按钮时,它会运行以下功能:

() => setTime(0)

这只是将time状态设置回0. 就这样。它根本不会触及对可观察区间的订阅。结果,间隔订阅将继续按顺序发出数字,这就是它似乎从最后一个值继续的原因。

解决方案

您的重置功能必须做的不仅仅是设置time0. 它的具体作用取决于您的具体用例。例如,它可以结束订阅、结束订阅并创建一个新订阅,或者重置现有订阅。我已经包含了一个代码示例,用于结束订阅的基本方式:

const {
  StrictMode,
  useCallback,
  useRef,
  useState,
} = React;
const { interval } = rxjs;
const rootElement = document.getElementById("root");

function useCounter() {
  const [time, setTime] = useState(0);
  const [timerOn, setTimerOn] = useState(false);
  const observable$ = interval(1000);
  const subscription = useRef();

  const start = useCallback(() => {
    setTimerOn(true);

    subscription.current = observable$.subscribe((result) => {
      console.log(result);
      setTime(result);
    });
  });

  const stop = useCallback(() => {
    setTimerOn(false);
    subscription.current.unsubscribe();
  });

  const reset = useCallback(() => {
    setTime(0);
    setTimerOn(false);
    subscription.current.unsubscribe();
  });

  return {
    time,
    timerOn,
    start,
    stop,
    reset
  };
}

function Counter() {
  const { time, timerOn, start, stop, reset } = useCounter();

  return (
    <div>
      <h1>{time}</h1>
      <br />
      {!timerOn && <button onClick={() => start()}>Start</button>}
      {time > 0 && <button onClick={() => reset()}>Reset</button>}
    </div>
  );
}

function App() {
  return <Counter />;
}

ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/rxjs@^7/dist/bundles/rxjs.umd.min.js"></script>


推荐阅读