skip to Main Content

I’m learning the useEffect; I’m running into an exercise with a non-empty independency array since I’m passing the index of the array.

The problem is that I get same name repeated.

This is my code and below is the result.

let users = ['Oliver', 'Thomas', 'George', 'George', 'William']
export default function App() {
  const [index, setIndex] = useState(0);
  console.log('RENDER');
  useEffect(() => {
    console.log('Hello ' + users[index]);
    console.log('Side Effect RUNS!');
    setTimeout(() => setIndex(index => index + 1), 1000)
    if (index === users.length - 1) {
      return
    }
  }, [index])
}

RESULT:

RENDER

Hello Oliver

Side Effect RUNS!

RENDER

Hello Thomas

Side Effect RUNS!

RENDER

Hello George

Side Effect RUNS!

RENDER

Hello George

Side Effect RUNS!

RENDER

Hello William

Side Effect RUNS!

RENDER

Hello undefined

Side Effect RUNS!

RENDER

Hello undefined

Side Effect RUNS!

RENDER

Hello undefined

Side Effect RUNS!

Also as you can see, I get undefined.

How can I solve the problem?

3

Answers


  1. It will run and print each user value and will not print undefined and will not render same output:

    import { useState, useEffect } from "react";
    
    let users = ['Oliver', 'Thomas', 'George', 'George', 'William'];
    
    export default function App() {
      const [index, setIndex] = useState(0);
    
      console.log('RENDER');
      useEffect(() => {
        console.log('Hello ' + users[index]);
        console.log('Side Effect RUNS!');
    
        if (index < users.length - 1) {
          let timeOut = setTimeout(() => {
            setIndex(preIndex => preIndex + 1);
          }, 1000);
    
          return () => {
            clearTimeout(timeOut); // Clean up the timeout on component unmount or re-render
          };
        }
      }, [index]);
    
      return (
        <div>
          <p>Index: {index}</p>
        </div>
      );
    }
    
    Login or Signup to reply.
  2. Try the following solution, which will make it possible for you to reiterate the list of users without displaying undefined:

    let users = ['Oliver', 'Thomas', 'George', 'George', 'William']
    export default function App() {
      const [index, setIndex] = useState(0);
      console.log('RENDER');
      useEffect(() => {
        console.log('Hello ' + users[index]);
        console.log('Side Effect RUNS!');
        setTimeout(
          () =>
          setIndex((index) => {
            if (index + 1 > users.length - 1) {
              return 0;
            }
    
            return index + 1;
          }),
          1000
        );
      }, [index])
    }
    Login or Signup to reply.
  3. Callback inside useEffect gets called every time a dependency changes, this callback will change index every time it runs and changing index will re-render component, which will cause the callback inside useEffect to re-run again and ofcourse it’s a infinite loop.
    Returning from the function when index is last, won’t change anything, that’s gonna break the current call but it won’t stop from calling callback in the next render which is bound to happen.
    You can add a condition when setting a timeout, to only change the value of index when there’s item next to it.

    let users = ['Oliver', 'Thomas', 'George', 'George', 'William']
    export default function App() {
      const [index, setIndex] = useState(0);
      console.log('RENDER');
      useEffect(() => {
        console.log('Hello ' + users[index]);
        console.log('Side Effect RUNS!');
        setTimeout(() => {
          if (users[index + 1] !== undefined) 
            setIndex(index => index + 1)
        }, 1000)
      }, [index])
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search