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
.
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
2
Answers
You’re absolutely correct in your understanding of why the infinite loop occurs. The issue arises because the
todos
array is included as a dependency in theuseEffect
hook, so every timesetTodos
is called, the todos state changes, triggering theuseEffect
again, which leads to infinite rerenders.Solution:
Remove todos from the dependency array: For fetching data on the initial mount, you only need an empty dependency array [] so that the effect runs only once when the component is mounted.
Handle new todos without refreshing: To handle the addition of new todos without needing to refresh the page, you should update the todos state directly after creating a new todo. This way, the new todo will be displayed immediately.
Here’s how you can adjust your code:
Explanation:
useEffect
with Empty Dependency Array:addTodo
Function:addTodo
function handles adding a new todo. After successfully adding a new todo to the backend, the new todo is appended to the existingtodos
state using thesetTodos
function. This allows the new todo to be immediately reflected in the UI without needing to refresh the page.Handling Updates or Deletes
If you need to handle updates or deletes, you can follow a similar approach by updating the
todos
state accordingly:This approach ensures your UI remains in sync with the backend data without the need for page refreshes.
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:
The step that you’re missing, is separating these scenarios.
You would like to get something like this:
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.