Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Infinite re-renders in react due to useEffect hook

I used useState hook for a todos array

const [todos, setTodos] = useState([]); `

I’m using this array to display and index of all todos. I also need the todos for the initial mount, so I’m using useEffect hook.
`

 useEffect(() => {
    const getTodoData = async () => {
      const { data } = await axios.get(`${BASE_URL}/todos`);
      setTodos(data);
    };
    getTodoData();
 }, [todos]);

However, the above code generates infinite rerenders and infinite requests are made to ${BASE_URL}/todos.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I understand why this is happening. Correct me if I’m wrong but I think when I setTodos(data); the todos array changes, ie the state changes, ie the dependency in the useEffect hook [todos] changes. Due to this, the setup function runs, it makes the request, and setTodos(data); again. Hence the infinite loop.

I saw other posts related to this, and almost everyone was saying to just remove the dependency. But what I don’t understand is, if we were to remove the dependency, then after making a new todo, we would have to refresh the page to see the changes reflected. I don’t think that’s feasible.

If there is a solution to making the new todo appear on the page without refreshing, please help me

>Solution :

I think you’re missing a step and that was causes you that issue.

You have an array of todos and that’s great, with that array you can display your todos.

Now comes the part of thinking – when would the array change?
I can think of this scenarios:

  1. Initial loading of todos
  2. Adding new todo
  3. Removing an existing todo

The step that you’re missing, is separating these scenarios.
You would like to get something like this:

const [todos, setTodos] = useState([]);

useEffect(() => {
   const getTodoData = async () => {
     const { data } = await axios.get(`${BASE_URL}/todos`);
     setTodos(data);
   };
   getTodoData();
}, []); // This use effect will do scenario 1

// Use this function to create new todo
const addTodo = (newTodo) => {
  const { data } = await axios.post(`${BASE_URL}/todos`, { newTodo });
  
  // assuming the returned data is all todos from the backend
  setTodos(data);
}

// Use this function to remove existing todo
const removeTodo = (existingTodoId) => {
  const { data } = await axios.delete(`${BASE_URL}/todos/${existingTodoId}`);

  // assuming the returned data is all todos from the backend
  setTodos(data);
}

Doing this way you won’t encounter the issue of infinite rerenders and also you keep you data updated.

P.S
I suggest you to use @tanstack/react-query library to handle this kind of request, it’ll make your code cleaner and easier to work with.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading