Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

287
Visualizações
How to increment a state variable every second in React

I have a list of images in my code for this component called "url". I also have a state variable called currImageIndex. What I want to happen is every time this component is rendered, I would like to start a timer. Every second this timer runs, I would like to increment my state variable currImageIndex. When currImageIndex + 1 is greater than or equal to url length, I would like to reset currImageIndex to zero. The overall goal is to simulate an automatic slideshow of images by just returning <img src={url[currImageIndex]}>. However, I am having issues with incrementing my state variable. I followed some code I found on here, but I can't figure out how to get the increment working. Here is my code.

const { url } = props;
  const [currImageIndex, setCurrImageIndex] = useState(0);
  console.log(url)
  const increment = () => {
    console.log(url.length)
    console.log(currImageIndex)
    if (currImageIndex + 1 < url.length) {
      setCurrImageIndex((oldCount) => oldCount + 1)
    }
    else {
      setCurrImageIndex(0)
    }
  }
  useEffect(() => {
    const id = setInterval(increment, 1000);

    return () => clearInterval(id);
  }, []);

  return (
    <div className={styles.container}>
      <div className={styles.header}>Preview of GIF:</div>
      <img src={url[currImageIndex]} alt="GIF Preview" className={styles.image} />
      <div>{currImageIndex}</div>
    </div>
  );

When I run this with a url of size 2, the third to last line ("{currImageIndex}") displays the 1 then 2 then 3 and so on. It does not reset ever. My console.log(url.length) prints 2 and my console.log(currImageIndex) prints 0. What I want to happen is currImageIndex should be 0, 1, 0, 1, 0, 1,.... Can anyone help me understand what I am doing wrong? Thank you!

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

The reason is that the callback passed on setInterval only access the currImageIndex variable in the first render, not the new value while render so you will always get currImageIndex = 0 and pass the condition if (currImageIndex + 1 < url.length). I update your code and make it work like your expectation: https://stackblitz.com/edit/react-y6fqwt

about 4 years ago · Juan Pablo Isaza Relatório

0

Issue

The issue here is you've a stale enclosure of the currImageIndex state value from the initial render when the increment callback was setup in the interval timer. You're correctly using a functional state to increment the currImageIndex value, but the currImageIndex value in the increment function body is and always will be that of the initial state value, 0.

Solution

A common solution here would be to use a React ref to cache the currImageIndex state so the current value can be accessed in callbacks.

Example:

const [currImageIndex, setCurrImageIndex] = useState(0);
const currentImageIndexRef = useRef();

useEffect(() => {
  // cache the current state value
  currentImageIndexRef.current = currentImageIndex;
}, [currImageIndex]);

const increment = () => {
  // access the current state value
  if (currentImageIndexRef.current + 1 < url.length) {
    setCurrImageIndex((oldCount) => oldCount + 1)
  }
  else {
    setCurrImageIndex(0)
  }
}

useEffect(() => {
  const id = setInterval(increment, 1000);
  return () => clearInterval(id);
}, []);

A simpler solution is to just access the url value that is closed over in component scope with the state updater callback. Use a ternary operator to check if adding 1 to the current value is still less than the url length and state + 1, otherwise reset by returning 0. Note however that if the url array is dynamic and the length changes this solution breaks for the same reason, the url value from the initial render is closed over in scope.

const increment = () => {
  setCurrImageIndex((count) => count + 1 < url.length ? count + 1 : 0);
}

And IMO the simplest solution is to just increment the currImageIndex state always and take the modulus of the url length to always compute a valid, in-range index value. If the url array changes, it doesn't matter as the modulus function will always compute a valid index.

const { url } = props;
const [index, setIndex] = useState(0);
const increment = () => setIndex(i => i + 1);

useEffect(() => {
  const id = setInterval(increment, 1000);
  return () => clearInterval(id);
}, []);

const currImageIndex = index % url.length;

return (
  <div className={styles.container}>
    <div className={styles.header}>Preview of GIF:</div>
    <img src={url[currImageIndex]} alt="GIF Preview" className={styles.image} />
    <div>{currImageIndex}</div>
  </div>
);

Edit how-to-increment-a-state-variable-every-second-in-react

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda