React: weird closure bug caused by setInterval

I have a component where there is a counter and a button to increment it. After the counter reaches to 5 we cannot increment it further. And there is a checkbox as well, when checked, the counter will increment by 1 every second.

The code is fairly straightforward


export default function App() {
  const [isActivated, setIsActivated] = useState(false);
  const [count, setCount] = useState(1);

  const incrementCount = () => {
    console.log("count inner", count);
    if (count < 5) {
      setCount((c) => c + 1);
    }
  };

  const timerRef = useRef(null);
  console.log("count outer", count);

  useEffect(() => {
    if (isActivated) {
      timerRef.current = setInterval(incrementCount, 1000);
    } else {
      clearInterval(timerRef.current);
    }
  }, [isActivated]);

  return (
    <div>
      <h1>{count}</h1>
      <input
        type="checkbox"
        onClick={(e) => {
          setIsActivated(e.target.checked);
        }}
      />
      <label>activate internal</label>
      <br />
      <br />
      <button onClick={incrementCount}>increment</button>
    </div>
  );
}

However, it has a bug: after you checked the checkbox, the counter will not stop at 5. Instead, it will keep incrementing. By putting console.log inside of incrementCount I found that the count state always stays at 1. I feel like it is a stale closure problem. But I cannot really pinpoint what exactly it is that is causing the problem.

Here is a live demo you can play with https://codesandbox.io/s/cranky-kepler-dedb6?file=/src/App.js

By the way, I know that I should have wrapped incrementCount inside of useCallback to make it stay referentially the same between renders. But that still doesn’t answer the question that why is that the count variable in incrementCount is stale.

93 thoughts on “React: weird closure bug caused by setInterval”

  1. After looking at a few of the blog articles on your site, I honestly
    like your technique of writing a blog. I saved as a favorite
    it to my bookmark website list and will be checking back in the near future.
    Please visit my web site too and let me know how you feel.

    Reply
  2. Great post. I was checking constantly this weblog
    and I’m impressed! Extremely helpful info particularly the remaining phase 🙂 I deal
    with such information much. I used to be seeking this particular info for a very
    lengthy time. Thanks and good luck.

    Reply
  3. Hi I am so thrilled I found your blog page, I really found you by accident, while I was searching on Bing for
    something else, Anyways I am here now and would
    just like to say kudos for a fantastic post and a all round
    interesting blog (I also love the theme/design), I don’t have time to read through it all at the
    moment but I have bookmarked it and also added in your RSS feeds, so when I have
    time I will be back to read much more, Please do keep up the awesome jo.

    Reply
  4. Today, I went to the beach with my kids. I found a sea shell and gave it to my 4 year old
    daughter and said “You can hear the ocean if you put this to your ear.” She placed the shell to her ear and screamed.
    There was a hermit crab inside and it pinched her ear.
    She never wants to go back! LoL I know this is entirely off topic but I had to tell someone!

    Reply
  5. With havin so much content and articles do you ever run into any issues of plagorism or copyright
    violation? My blog has a lot of unique content I’ve either written myself
    or outsourced but it appears a lot of it is popping it up
    all over the internet without my authorization. Do you know any methods to help prevent content from being stolen? I’d certainly appreciate it.

    Reply
  6. Howdy! I understand this is somewhat off-topic but I needed to ask.

    Does building a well-established website such as yours require a lot of work?
    I’m brand new to writing a blog but I do write in my diary on a daily
    basis. I’d like to start a blog so I can share my experience
    and feelings online. Please let me know if you have any suggestions or tips for new aspiring
    blog owners. Appreciate it!

    Reply
  7. Undeniably believe that which you said. Your favourite justification appeared
    to be on the internet the simplest factor to be aware of.
    I say to you, I certainly get irked even as
    other folks consider concerns that they just do
    not realize about. You managed to hit the nail upon the highest as neatly as outlined
    out the entire thing without having side effect ,
    other people could take a signal. Will probably be back
    to get more. Thanks

    Reply
  8. Attractive portion of content. I simply stumbled upon your
    weblog and in accession capital to claim that I acquire actually loved account your weblog posts.
    Anyway I’ll be subscribing to your feeds and even I success you get right
    of entry to consistently rapidly.

    Reply
  9. You actually make it seem so easy with your presentation but
    I find this topic to be really something which I
    think I would never understand. It seems too complex and
    extremely broad for me. I’m looking forward for your next post, I will try to get the hang of
    it!

    Reply
  10. I like the valuable info you provide in your articles.

    I will bookmark your blog and check again here regularly.
    I’m quite certain I’ll learn many new stuff right here!
    Good luck for the next!

    Reply
  11. My partner and I stumbled over here from a different web address
    and thought I might as well check things out. I like what I see so i am just following you.

    Look forward to finding out about your web page for
    a second time.

    Reply

Leave a Comment