Want to display different text and array for few seconds

Viewed 75

I have such a problem:

I have an array of data, and I have an array of time. These are the arrays:

  const Reps = {
    TimeOfMove: [1, 2.5, 3, 3.5, 4.5, 5, 6, 10, 12, 13, 14, 15.5],
    ScoreOfMove: [60, 85, 42, 60, 70, 80, 90, 100, 90, 40, 0, 20],
  };

After a second I want to display the number 60, after 2.5 seconds the number 85, and so these ...

Also i want to display the ScoreOfMove array after a second as: [60,0... 0], after 2.5 seconds the array as: [60,85,0...0].

This is the code I've been trying to do so far, but it's not working for me


import React, { useEffect, useState } from 'react';
import "./styles.css";

const Reps = {
  TimeOfMove: [1, 2.5, 3, 3.5, 4.5, 5, 6, 10, 12, 13, 14, 15.5],
  ScoreOfMove: [60, 85, 42, 60, 70, 80, 90, 100, 90, 40, 0, 20],
};
let i = 0;

export default function App() {
  const [time, setTime] = useState('');
  const [timeArr, setTimeArr] = useState([]);

  useEffect(() => {
      setTimeout(() => {
        setTime(Reps.ScoreOfMove[i])
        i++;
      }, Reps.TimeOfMove[i] * 1000)
  }, [time])
  
  return (
    <div className="App">
      {time}
      {timeArr}
    </div>
  );
}

I want to display different text each time,and different array each time, according to the time it appears.

2 Answers

setTimeout executes only once after the specified timeout interval. So your code is only running one time. It may be better to move the logic out to a different (recursive) function, as one example, so you can call setTimeout for each item in the Reps.TimeOfMove array:

const setNextTime = i => {
    if (i >= Reps.TimeOfMove.length) {
        return;    // We're at the end so don't do anything
    }

    setTimeout(() => {
        setTime(Reps.ScoreOfMove[i]);
        setNextTime(i++);
    }, Reps.TimeOfMove[i] * 1000);
}

useEffect(() => {
    setNextTime(0);
}, []);

Matt is right, so try with this:

const Reps = {
  TimeOfMove: [1, 2.5, 3, 3.5, 4.5, 5, 6, 10, 12, 13, 14, 15.5],
  ScoreOfMove: [60, 85, 42, 60, 70, 80, 90, 100, 90, 40, 0, 20],
};

function App() {
  const [time, setTime] = React.useState();
  // Create a new array reference with the same length as ScoreOfMove filled with zeros
  const timeArr = React.useRef(new Array(Reps.ScoreOfMove.length).fill(0));

  React.useEffect(() => {
      let timer;
      let i = 0;
      
      const tick = () => {
        // Keeps a reference of current index
        // to be used inside setTimeout, and
        // increase real index reference by one for next tick validation
        const currentIndex = i++;
        timer = setTimeout(() => {
          // Update array index with corresponding value
          // Run this before setTime to keep things in sync
          timeArr.current[currentIndex] = Reps.ScoreOfMove[currentIndex];
          setTime(Reps.ScoreOfMove[currentIndex]);
          
          if (Reps.TimeOfMove[i]) { // if there is a next tick
            tick();
          }
        }, Reps.TimeOfMove[currentIndex] * 1000);
      }
      
      tick();
      
      return () => clearTimeout(timer); // Clear time out to prevent memory leak

  // No dependencies, to execute the effect one single time
  }, [])
  
  return (
    <div className="App">
      <p>{time}</p>
      <p>{timeArr.current.toString()}</p>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Related