setInterval loops over the first character
What was I trying to do?
Trying to display the page brand name one letter at a time, on page render..
What have you tried already to fix it?
What I tried is in no way logical, lazy fixed it by repeating the character index it kept omitting
Errors: none , just skipping (omission)
Overlook any inadequacy, I am still learning πΏ
function Brand({text, speed}) {
const [brandName, setBrandName] = useState("");
const indexRef = useRef(0);
useEffect(() => {
setBrandName("");
indexRef.current = 0;
console.log(indexRef);
const intervalId = setInterval(() => {
console.log('Before update:', brandName, indexRef.current); // Debugging log
setBrandName((prev) => {
console.log('Updating:', prev, text.charAt(indexRef.current)); // Debugging log
return prev + text.charAt(indexRef.current);
});
indexRef.current++;
console.log('After update:', brandName, indexRef.current); // Debugging log
if (indexRef.current >= text.length) {
clearInterval(intervalId);
}
}, speed);
return () => clearInterval(intervalId);
},[text, speed, brandName]);
return (
<span className='font-bold text-3xl'>{brandName}</span>
)
}
export default function Logo() {
return (
<Link to="/">
<div className='flex items-center gap-2'>
<img src="avatar.jpg" alt="logo" className='w-12 h-12 rounded-full'/>
<Brand text='MurWebsite' speed={400} />
</div>
</Link>
)
}
11 Replies
The problem is the dependency array. Remove brandName from it. The useEffect changes this value and it's a dependency, so you get infnite re-renders.
EsLint screams at me when I take it out of the dependency, and it doesn't make any difference if it's there or not
Please don't use useRef to store a state, even if it's 'temporary'.
Some advice based on the code you wrote:
1. Find the smallest state(s) that is changing in your component. (for your case it will be the length of the word, not the word itself)
2. Check if other things can be derived from those states. (in your case, the part of the word to display can be calculated from the length)
Also: general advice is to never put the state you are updating in your useEffect as a dependency of that useEffect. (ofc there are some exceptions)
I am not sure if you are misunderstanding what I said. Here is code that I tested and it works without any warning or errors:
Note that I also tested without removing that item from the dependency array and it did not work.
I did not use eslint on my test project. If the only reason you are writing wrong code is to obey what eslint is telling you, then you either need to modify the eslint configuration or stop using it.
Yes , I did this
I'll try this
I am still learning πΉ if I am to remove it completely I'll have to look up some syntax , or type everything manually which is a stress
Remove what completely? I think you are still misunderstanding. I removed only one comma and one variable name. You don't need to look up anything. My code is an exact copy and paste of your code with one very small change.
I just realized you are referring to the eslint.
Is the initial useState not supposed to be 0? , and if when the current length is greater than name length, why not return nothing π it feels like return 0 would just kickstart the whole loop again
I'll check it now, anyways, I'll drop feedback right after
Sorry, I meant..
I am not sure if you understand what Aoi said here: "Also: general advice is to never put the state you are updating in your useEffect as a dependency of that useEffect. (ofc there are some exceptions)"
It is exactly the same thing that I said but in different words. It is a widely known common bug in beginner's code when learning to use useEffect.
Ok I've seen this
Ok thanks a lot, I'll keep that in mind
I really didn't put it at first.. the underline only went away after I put it
Like you said, I need to make some changes to my EsLint settings
this worked out, thanks a lot
@ChooKing @Aoi
Great, btw you should also clear the interval when the
currentLength >= text.length
.Ok, that is much better π thanks