I’m learning ReactJS and my first project is online alarm.
So I decided to check out my clock if it has some bugs and… It has.
I checked some console logs of rendering function and memory using with F12 in Chrome.
You can see that every second I have more and more of rerenders.
import React, { useState, useEffect } from "react";
import classes from "./Clock.module.css";
import { useMemo } from "react";
const ClockCurrent = (props) => {
//*TODO:
//!If put console.log(time) you can see that useState is overused
//! and PC's memory overfilling, because
//! entity of rerenders getting bigger every second like
//! geometrical progression*
const [time, setTime] = useState(new Date());
const refreshClock = () => {
setTime(new Date());
};
useEffect(() => {
setInterval(refreshClock, 1000);
console.log(time);
}, [time]);
return (
<div className={classes.Clock}>
<h2>
{useMemo(
() =>
time.toLocaleTimeString("ru", {
timeZone: "Europe/Moscow",
}),
[time]
)}
</h2>
</div>
);
};
export default ClockCurrent;
In the code above you can see how I used useState() and useEffect() func.
useMemo didn’t help me at all, by the way.
Don’t think my realisation is right but it is what it is and hope I’ll fix this bug in memory using.
I have almost the same (differs only in .toLocateTimeString properties) code to getting the date and it has exactly same problem.
What I tried to do to solve it:
- Include useMemo() to my code
- Don’t use useState and useEffect
- Try lots of ways to relize the useState method
All of cases didn’t work at all excepting the 2nd, when I didn’t get tracebacks .
4
Answers
Task closed
So, thanks a lot! for helping with this issue, guys, you are the best one. You was really right says that useEffect triggers setInterval every time the
time
changes.So the solution is:
To the useEffect function adding a
return
an anonymic func withclearInterval
method:Thanks a lot again not only for solution but for explaining how useState and useEffect works as well. Now I understand it a bit deeply.
I did the same to gettingDate function.
If earlier I got overfilled memory, now it became cleared every ~7-10 seconds.
Because the logic in
useEffect
does three things:It executes whenever
time
changes:It creates a new interval:
And in that interval it updates
time
:If you only want the
useEffect
to run once when the component loads (so it only creates one interval), use an empty dependency array. Additionally, if auseEffect
produces side-effects like timeouts or intervals, it should also clean those up by returning a clean-up function. For example:If you also want to output the value of
time
whenever it changes, that’s an entirely different effect:Though you could also just put that directly in the component:
Since every time state is updated the component will re-render anyway.
you have defined [time] as a dependency in your useEffect. This means that this hook will always be called when the time variable is changed. This means that you define a new interval every second, which will cause your component to be rendered again.
You have to make sure that the interval is defined exactly once when your component is mounted and also released again when your component is dismounted.
In the provided code, the useState is updating because it’s part of the component’s state and is being used in the useEffect hook, which triggers every second due to the interval set by setInterval. The issue is that you are creating a new interval on every render, which leads to multiple intervals running simultaneously, causing excessive updates and memory consumption.
To fix this issue, you should clear the interval when the component unmounts to avoid multiple intervals running at the same time. You can do this by returning a cleanup function from the useEffect hook.
Try this code: