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

React中使用Map实现多行独立倒计时的技术求助

Fixing Independent Countdowns for Each Car in React

Hey there! The problem with your current code is that all your car rows are sharing the same single time and seconds state, plus a single timer instance. That's why every countdown updates together instead of being independent. Let's adjust this to track each countdown separately.

Here's how to refactor your code:

  1. Update your state structure
    Instead of having global time and seconds, we'll store each car's countdown data directly in the data array (keeping it in the data array keeps things straightforward). We'll also track multiple timers using an object instead of a single variable.

  2. Modify timer management functions
    We need to make startTimer and countDown accept a car ID so they know which countdown to update. We'll store timers in an object where keys are car IDs, so we can clear specific timers when needed.

  3. Adjust the addCar function
    When adding a new car, initialize its countdown state (3600 seconds) and start its timer right away.

Here's the full refactored code:

class Example extends React.Component { 
  constructor() { 
    super(); 
    this.state = { 
      data: [ 
        { "id": 1, "car": 'Audi 2018', seconds: 3600, time: {} } 
      ] 
    }; 
    this.timers = {}; // Track multiple timers by car ID
    this.startTimer = this.startTimer.bind(this); 
    this.countDown = this.countDown.bind(this); 
  } 

  secondsToTime(secs){ 
    let hours = Math.floor(secs / (60 * 60)); 
    let divisor_for_minutes = secs % (60 * 60); 
    let minutes = Math.floor(divisor_for_minutes / 60); 
    let divisor_for_seconds = divisor_for_minutes % 60; 
    let seconds = Math.ceil(divisor_for_seconds); 
    return { 
      "h": hours, 
      "m": minutes, 
      "s": seconds 
    }; 
  } 

  componentDidMount() { 
    // Initialize time for each car and start their timers
    this.state.data.forEach(car => {
      const timeLeftVar = this.secondsToTime(car.seconds);
      this.setState(prevState => ({
        data: prevState.data.map(item => 
          item.id === car.id ? {...item, time: timeLeftVar} : item
        )
      }));
      this.startTimer(car.id);
    });
  } 

  startTimer(carId) { 
    // Only start if no timer exists for this car
    if (!this.timers[carId]) { 
      this.timers[carId] = setInterval(() => this.countDown(carId), 1000); 
    } 
  } 

  countDown(carId) { 
    this.setState(prevState => {
      // Find the car we need to update
      const updatedData = prevState.data.map(item => {
        if (item.id === carId) {
          const newSeconds = item.seconds - 1;
          const newTime = this.secondsToTime(newSeconds);
          
          // If we hit zero, clear the timer
          if (newSeconds === 0) {
            clearInterval(this.timers[carId]);
            delete this.timers[carId];
          }
          
          return {...item, seconds: newSeconds, time: newTime};
        }
        return item;
      });
      
      return { data: updatedData };
    });
  } 

  addCar = () =>{ 
    const newId = this.state.data.length + 1; // Simple ID generation
    const newCar = { 
      "id": newId, 
      "car": `New Car ${newId}`, 
      seconds: 3600, 
      time: this.secondsToTime(3600) 
    };
    
    this.setState(prevState=>({ 
      data: [...prevState.data, newCar] 
    }), () => {
      // Start the timer after the state updates
      this.startTimer(newId);
    });
  } 

  render() { 
    return ( 
      <div> 
        {this.state.data.map(row=> 
          <ul key={row.id}> 
            <li>
              Car: {row.car} <b>Finish:</b> 
              h: {row.time.h} m: {row.time.m} s: {row.time.s}
            </li> 
          </ul> 
        )} 
        <button onClick={this.addCar}>Add Car</button> 
      </div> 
    ) 
  } 

  // Clean up timers when component unmounts
  componentWillUnmount() {
    Object.values(this.timers).forEach(timer => clearInterval(timer));
  }
}

Key changes explained:

  • this.timers object: Stores individual timers for each car, using the car's ID as the key. This lets us start/stop timers for specific cars without affecting others.
  • Per-car state: Each car object now has its own seconds and time properties, so updates are isolated to the specific row.
  • startTimer and countDown accept carId: These functions now target a specific car instead of updating global state.
  • Component cleanup: Added componentWillUnmount to clear all timers when the component is removed, preventing memory leaks.

This way, every car gets its own independent countdown that starts when the car is added, and stops when it hits zero—no more shared timers!

内容的提问来源于stack exchange,提问作者Laura delgado

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:53:31