GithubHelp home page GithubHelp logo

Comments (2)

AliHaiderPgm avatar AliHaiderPgm commented on April 28, 2024

The issue you're experiencing is due to the way React handles updates and re-renders. When your component first renders, ref.current is initialized to 0. However, in the same render cycle, you're incrementing ref.current inside a useEffect hook without any dependencies. This means that the effect will run after every render, including the initial one. So, on the first render, ref.current is incremented from 0 to 1, then on the second render it's incremented again from 1 to 2, and so on. That's why you're seeing 2, 3, 4, etc., instead of 1, 2, 3, etc.

To fix this, you need to ensure that ref.current is only incremented once per render cycle. One way to do this is to use a separate state variable to track whether it's the first render or not. Here's how you can modify your code:

First Method is using useState hook:

//previous code
const [isFirstRender, setIsFirstRender] = useState(true);
const ref = useRef(0);
 useEffect(() => {
   if (isFirstRender) {
   setIsFirstRender(false);
   } else {
     ref.current = ref.current + 1;
   }
 });
//previous code

Second method is using useRef hook:

//previous code
const log = useRef(true)
const ref = useRef(0);
useEffect(() => {
    if (log.current) {
      log.current = false
    } else {
      ref.current = ref.current + 1;
    }
  });
//previous code

from react.

rickhanlonii avatar rickhanlonii commented on April 28, 2024

@AliHaiderPgm thats a good thought, but the effect doesn't run until after render so it will show 0,1,2,3,4 as expected as written outside of strict mode. Your fix does solve the issue, because it skips the count for the first strict mode effect, but if this was run in prod it would miss the first render, since strict mode doesn't run in prod.

The issue is that React 18 introduced a new feature for StrictMode that immediately unmounts and remounts effects to ensure they're properly cleaned up, to catch bugs like this. That's why it worked before 18 and doesn't work as expected.

Check out this sandbox, and notice that is works if you remove from index.js: https://codesandbox.io/p/sandbox/blissful-darkness-xyz6m6?file=%2Fsrc%2Findex.js%3A10%2C18

The reason this is a bug is because when the component unmounts, you're not resetting the ref. That means when you use certain features, the ref won't be reset when you expect it to. For example, when Fast Refresh updates the component, you would expect the render count to reset to 0, but in your version the render count gets "stuck" at the current value and you need to hard refresh the page to reset it to 0.

In future versions we plan to reset refs for you in strict mode to align with the production behavior (#25049), but hopefully this shows the value of the new strict mode behavior.

Until that lands, to fix this, you can reset the ref when the component unmounts. You need two effects to do this because the effect that updates the count will destroy on every render, but you only want to reset on unmount:

const ref = useRef(0);

useEffect(() => {
  ref.current = ref.current + 1;
});

useEffect(() => {
  return () => {
    ref.current = 0;
  };
}, []);

Note: we also have a planned feature to support doing this in a single effect by allowing you to specify different functions that run for create vs update in the same effect: #25744

from react.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.