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

222
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 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