Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

220
Vistas
Why is ref value incrementing twice

I have this code here:

export default function App() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(0);
  const reff = useRef(0);

  useEffect(() => {
    
      const id = setInterval(() => {

      setCount((c) => {
        console.log({ step }, "reff.current before incr ", reff.current);
        reff.current = reff.current + step;
        console.log("ref.curret after incr ", reff.current);
        return c + step;
      });

    }, 6000);

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


  return (
    <>
      <h1>Count:{count}</h1>
      <h1>Step: {step}</h1>
      <input
        type="button"
        onClick={(e) => setStep((prevStep) =>(prevStep + 1))}
        value="+ step"
      />
    </>
  );
}

You can view it here: https://codesandbox.io/s/gracious-roentgen-31ntb?file=/src/App.js:0-817

Note that I'm incrementing ref inside setCount callback

When the component loads a setInterval is started. If I trigger the useEffect again by incrementing step before 6 seconds pass, it clears the setInterval and creates a new one.

And now if I don't increment step again and wait for 6 seconds, I see step: 1 reff.current before incr, 0 for the first time the setInterval callback is called.

After incrementing in the next line(reff.current = reff.current + step) I see "ref.curret after incr ", 1

When the setInterval callback is called again after 6 seconds, I see

step: 1 reff.current before incr, 2 //how did this become 2

I don't understand how the value of reff.current is 2.

This only happens when I increment the step(which clears the first interval). If I set the initial step to 1 and don't increment it, I see expected values.. Just checked again. It doesn't work as expected.

I can't understand why the value of reff.current is 2 when the setInterval callback is called the second time.

Go to the sandbox link and

  1. Click on the +step button once

  2. Open the console and see

log 1:{step: 1} "reff.current before incr "0
log 2: ref.curret after incr 1
//second time callback is called
log 3: {step: 1} "reff.current before incr "2 //this should be 1
log 4: ref.curret after incr 3```
about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Your problem happens because you are performing a side effect (updating reff.current) inside the updater function passed to the setCount.

The beta react docs say that:

Updater functions run during rendering, so updater functions must be pure and only return the result. Don’t try to set state from inside of them or run other side effects. In Strict Mode, React will run each updater function twice (but discard the second result) to help you find mistakes.

You are running your app in StrictMode. To verify it comment it:

const rootElement = document.getElementById('root');
ReactDOM.render(
  // <StrictMode>
  <App />,
  // </StrictMode>,
  rootElement
);

and the problem doesn't happen anymore.

about 4 years ago · Juan Pablo Isaza Denunciar

0

Can you please try out this code below,


Not sure about the exact reason why the value was incremented, but using it directly instead of returning from a function, did work as expected. Also it works for further step increment.


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

export default function App() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(0);
  const reff = useRef(0);
  useEffect(() => {
    const id = setInterval(() => {
      console.log({ step }, "reff.current before incr ", reff.current);
      debugger;
      //  ------ modified here
      let newVal = reff.current + step;
      reff.current = newVal;
      console.log("ref.curret after incr ", reff.current);
      setCount(newVal);
      //  ------ modified here
    }, 6000);
    return () => clearInterval(id);
  }, [step]);

  return (
    <>
      <h1>Count:{count}</h1>
      <h1>Step: {step}</h1>
      <input
        type="button"
        onClick={(e) => {
          e.preventDefault();
          setStep((prevStep) => {
            console.log(prevStep);
            return Number(prevStep) + 1;
          });
        }}
        value="+ step"
      />
    </>
  );
}

The image of the log logs

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda