You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用React Hooks实现带启停按钮的循环计数器?

Fixing Your React Counter with setInterval

Let's break down what's going wrong with your current code and build a working version that meets all your requirements: click Start to begin incrementing, click Stop to halt and reset to 1, and loop back to 1 automatically when the counter hits 10.

Issues in Your First Code

  • You’re creating a new setInterval every time the component re-renders (which happens on every state change) when start is true. This leads to multiple overlapping intervals running at once, making the counter speed up unexpectedly.
  • Using var for the interval variable is risky—it’s function-scoped and can lead to inconsistent references as the component re-renders.
  • Your state update syntax (like setStopStatus((prev) => (prev = true))) is incorrect. You should return the new value directly, not assign it.

Issues in Your Second Code

  • The empty dependency array in useEffect runs the interval immediately on component mount, which is why it starts automatically without clicking Start.
  • Storing the interval ID as a global variable (var handle) means it won’t reset properly on component re-renders or unmounts, leading to leftover intervals running in the background.
  • You’re still creating duplicate intervals when start is true, which causes the counter to behave erratically.

Working Implementation

Here’s a clean, reliable version that fixes all these problems:

import React, { useState, useEffect, useRef } from "react";

function App() {
  const [count, setCount] = useState(1);
  const [isRunning, setIsRunning] = useState(false);
  // Use useRef to persist the interval ID across re-renders without triggering state changes
  const intervalRef = useRef(null);

  // Manage interval creation and cleanup with useEffect
  useEffect(() => {
    if (isRunning) {
      intervalRef.current = setInterval(() => {
        setCount(prev => {
          // Loop back to 1 when we reach the target value (10)
          return prev === 10 ? 1 : prev + 1;
        });
      }, 1000);
    }

    // Cleanup function: clear interval when component unmounts or isRunning changes
    return () => {
      clearInterval(intervalRef.current);
    };
  }, [isRunning]);

  const handleStart = () => {
    setIsRunning(true);
  };

  const handleStop = () => {
    setIsRunning(false);
    setCount(1); // Reset counter to default value 1
  };

  return (
    <div>
      <h1 style={{ padding: "5px", margin: "5px" }}>{count}</h1>
      <button style={{ padding: "5px", margin: "5px" }} onClick={handleStop}>
        Stop
      </button>
      <button style={{ padding: "5px", margin: "5px" }} onClick={handleStart}>
        Start
      </button>
    </div>
  );
}

export default App;

Key Improvements

  • useRef for Interval ID: We use useRef to store the interval ID so it persists across re-renders without causing unnecessary state updates.
  • Controlled useEffect: The effect only runs when isRunning changes, so we create exactly one interval when starting and clear it immediately when stopping or unmounting.
  • Simplified State: Instead of separate start and stop states, we use a single isRunning boolean to avoid conflicting state values.
  • Proper Loop Logic: The counter’s increment logic handles the loop back to 1 directly in the setCount callback, ensuring consistent behavior.
  • Memory Leak Prevention: The cleanup function in useEffect guarantees we always clear the interval, even if the component unmounts unexpectedly.

How It Works

  • Click Start: Sets isRunning to true, triggering the useEffect to start the interval. The counter increments every second, looping back to 1 when it hits 10.
  • Click Stop: Sets isRunning to false, which triggers the cleanup function to clear the interval. It also resets the counter back to 1 immediately.
  • No overlapping intervals: We only create a new interval when isRunning switches from false to true, and we always clear the old interval first.

内容的提问来源于stack exchange,提问作者blaster carter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:22:56