Why does react rerender this at the component level but not when using a hook?

I've been toying with a type-writer effect in react and cant understand why react's lifecycle is working this way. Can someone explain why react is re-rendering the <WithoutHook/> component such that it doesnt work While the <WithHook/> one does? https://codesandbox.io/s/damp-moon-v24dzf?file=/src/App.jsx Notice 'strict mode' is on and if you disable it, it still breaks when not using a hook.
CodeSandbox
damp-moon-v24dzf - CodeSandbox
damp-moon-v24dzf using react, react-dom, react-scripts
8 Replies
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
jakeman
jakeman2y ago
Huh, this is really interesting. Im still confused on how changing the index from a ref to a variable inside the effect schedules it to run after setTypingText(). I remember reading somewhere that setState is async. Any concrete examples of this? Or in other words do you need to await setTypingText in this case?
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
jakeman
jakeman2y ago
After more testing this works:
export const WithoutHook = () => {
const [typingText, setTypingText] = useState("");
const text = "hello";
const index = useRef(0);

useEffect( () => {
const interval = setInterval(() => {
if (index.current < text.length) {
let newText = text[index.current];
setTypingText((prevMessage) => prevMessage + newText);
} else {
clearInterval(interval);
}
index.current++;
}, 500);
return () => clearInterval(interval);
}, []);

return (
<div>
<h1>{typingText}</h1>
</div>
);
};
export const WithoutHook = () => {
const [typingText, setTypingText] = useState("");
const text = "hello";
const index = useRef(0);

useEffect( () => {
const interval = setInterval(() => {
if (index.current < text.length) {
let newText = text[index.current];
setTypingText((prevMessage) => prevMessage + newText);
} else {
clearInterval(interval);
}
index.current++;
}, 500);
return () => clearInterval(interval);
}, []);

return (
<div>
<h1>{typingText}</h1>
</div>
);
};
the line that fixes it is let newText = text[index.current]; Still confused hahha No doubt the most error prone aspect of react (atleast that I run into)
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
jakeman
jakeman2y ago
Than how do you clear the interval?
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
jakeman
jakeman2y ago
Yeah makes sense. Thanks for the help dude
Want results from more Discord servers?
Add your server