I'm learning React and can't avoid a memory leak. In the code below I've tried to use [this codepen][1] in React, and it works, until the initialLoad is set to false and then the Preloader component continuously logs the error below.
Is this an issue with my implementation of useRef? I've tried following patterns to cleanup setTimeout and conditionally calling the animate() function if the child is mounted, but no luck. How can I avoid this error?
Error
"Uncaught TypeError: text2.current is null
setMorph Preloader.jsx:47
doMorph Preloader.jsx:42
animate Preloader.jsx:83"
In Parent Component
const { initialLoad, setInitialLoad } = useGlobalState();
useEffect(() => {
if (initialLoad) {
const timer = setTimeout(() => {
setInitialLoad(false);
}, 4600);
return () => {
clearTimeout(timer)
}
}
}, [initialLoad]);
return (
<div className='browser-wrapper'>
{initialLoad &&
<Preloader initialLoad={initialLoad} />
}
...
)
Preloader Component
const Preloader = ({ initialLoad }) => {
const text1 = useRef(null)
const text2 = useRef(null)
// Insert Text String and Morph tuning adjusments
const morphTime = .68;
const cooldownTime = 0.12;
let textIndex = texts.length - 1;
let time = new Date();
let morph = 0;
let cooldown = cooldownTime;
text1.current = texts[textIndex % texts.length];
text2.current = texts[(textIndex + 1) % texts.length];
function doMorph() {
morph -= cooldown;
cooldown = 0;
let fraction = morph / morphTime;
if (fraction > 1) {
cooldown = cooldownTime;
fraction = 1;
}
setMorph(fraction);
}
// A lot of the magic happens here, this is what applies the blur filter to the text.
function setMorph(fraction) {
text2.current.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
text2.current.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;
fraction = 1 - fraction;
text1.current.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
text1.current.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;
text1.current.textContent = texts[textIndex % texts.length];
text2.current.textContent = texts[(textIndex + 1) % texts.length];
}
function doCooldown() {
morph = 0;
text2.current.style.filter = "";
text2.current.style.opacity = "100%";
text1.current.style.filter = "";
text1.current.style.opacity = "0%";
}
// Animation loop, which is called every frame.
function animate() {
requestAnimationFrame(animate);
let newTime = new Date();
let shouldIncrementIndex = cooldown > 0;
let dt = (newTime - time) / 1000;
time = newTime;
cooldown -= dt;
if (cooldown <= 0) {
if (shouldIncrementIndex) {
textIndex++;
}
doMorph();
} else {
doCooldown();
}
}
useEffect(() => {
let mounted = true;
if (mounted) {
animate();
}
return () => mounted = false;
})
return ( --- JSX follows
```
[1]: https://codepen.io/Valgo/pen/PowZaNY?ref=devawesome.io