Search code examples
reactjsfor-loopduplicates

Why is the for loop counting the same index twice?


i have a weird issue with React and the timout function. For some reason i want a string to be added to a useEffect letter by letter. So i have written this code:

const [placeholder, setPlaceholder] = useState < string > ('')

useEffect(() => {
    const str = "How may I help you today?";
    const letters = Array.from(str);

    const addLetterWithDelay = (index: number) => {
        if (index < letters.length) {
            setTimeout(() => {
                setPlaceholder(prevPlaceholder => prevPlaceholder + letters[index]);
                addLetterWithDelay(index + 1);
            }, 1000); // Delay of 1 second
        }
    };

    addLetterWithDelay(0); // Start adding letters from index 0
}, []);

The problem is that the letter is setting it twice So the output will be: HHooww mmaayy II hheellpp yyoouu ttooddaayy?? even if i check with a statement if the last char of the placeholder is the same as letters[index] or not, it still prints that it is not the same and go executing


Solution

  • Modify your useEffect to:

     useEffect(() => {
        const str = "How may I help you today?";
        const letters = Array.from(str);
        let timerId: NodeJS.Timeout; // Declare a variable to hold the timeout ID
    
        const addLetterWithDelay = (index: number) => {
            if (index < letters.length) {
                timerId = setTimeout(() => {
                    setPlaceholder(prevPlaceholder => prevPlaceholder + letters[index]);
                    addLetterWithDelay(index + 1);
                }, 1000); // Delay of 1 second
            }
        };
    
        addLetterWithDelay(0); // Start adding letters from index 0
    
        return () => clearTimeout(timerId); // Clear the timeout when the component is unmounted or the useEffect hook re-runs
    }, []);
    

    This manner, if your component re-renders and the useEffect hook is called again, the current timeout is cleared and the addLetterWithDelay method is terminated.