Majid Ainizoda
Majid Ainizoda

Reputation: 149

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop [another variant]

I read some articles on this topic, but it didn't helped. I think my problem is a little different

Here is my code:

import React, { useEffect } from 'react';
import { useState } from 'react';
import { useSelector } from 'react-redux';
import store from '../../store';
import ToDoAdder from '../ToDoAdder/ToDoAdder';

function ToDoList() {
  const [users, setUsers] = useState([]);
  const [todosState, setTodosState] = useState([]);

  useEffect(() => {
    fetchUsers();
    fetchData();
  }, []);

  const fetchUsers = async () => {
    const data = await fetch(`https://jsonplaceholder.typicode.com/users/`);
    const res = await data.json();
    console.log(res, 0);
    setUsers(res);
  };

  const fetchData = async () => {
    const data = await fetch('https://jsonplaceholder.typicode.com/todos/');
    const res = await data.json();

    const needed = res.slice(0, 10);
    setTodosState(needed);

    return res;
  };

  console.log(todosState);
  const todosWithUser = todosState.map((o) => {
    const user = users.filter((i) => o.userId === i.id)[0];
    o.user = user;
    return o;
  });

  store.dispatch({ type: 'add/todoArray', payload: { todos: todosWithUser } });

  const todos = useSelector((store) => store.toDos);
  // console.log(todos);
  return (
    /* some statement */
  );
}

export default ToDoList;

Tell me how can I solve this ? I know that my problem is in setTodosState, but I cant solve that

Upvotes: 1

Views: 315

Answers (2)

Ryan Le
Ryan Le

Reputation: 8412

Here is the problem with your code:

store.dispatch({ type: 'add/todoArray', payload: { todos: todosWithUser } });

Every time ToDoList is rendered, this dispatch will be invoke causing the redux state to change, and you also have this selector in your code:

const todos = useSelector((store) => store.toDos);

So it will again render ToDoList making the render loop infinite


So let's put your dispatch into eventHandler or a useEffect hook.

Upvotes: 1

Viet
Viet

Reputation: 12787

never call any change state inside component. It need to call it on the function or hooks effect:

useEffect(() => {
  const todosWithUser = todosState.map((o) => {
    const user = users.filter((i) => o.userId === i.id)[0];
    o.user = user;
    return o;
  });

  store.dispatch({ type: "add/todoArray", payload: { todos: todosWithUser } });
}, [todosState]);

Upvotes: 4

Related Questions