i was doing a todo list app on React, and, tring to handle the changes i got the following error:
Uncaught TypeError: prevTodos is not iterable
My handle function:
function handleAddTodo(e) {
const name = todoNameRef.current.value;
if (name === '') return;
setTodos((prevTodos) => {
return [...prevTodos, { id: v4(), name: name, complete: false }];
});
todoNameRef.current.value = null;
}
Full Code:
import React, { useState, useRef, useEffect } from "react";
import TodoList from "./TodoList";
import { v4 } from "uuid";
const LOCAL_STORAGE_KEY = 'todoApp.todos';
function App() {
const [todos, setTodos] = useState([]);
const todoNameRef = useRef();
useEffect(() => {
const storedTodos = localStorage.getItem(LOCAL_STORAGE_KEY);
if (storedTodos) setTodos(storedTodos);
setTodos();
}, []);
useEffect(() => {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos));
}, [todos]);
function handleAddTodo(e) {
const name = todoNameRef.current.value;
if (name === '') return;
setTodos((prevTodos) => {
return [...prevTodos, { id: v4(), name: name, complete: false }];
});
todoNameRef.current.value = null;
}
return (
<>
<TodoList todos={todos} />
<input ref={todoNameRef} type="text" />
<button onClick={handleAddTodo}>Add Todo</button>
<button>Clear Complete</button>
<div>0 left to do</div>
</>
);
}
export default App;
CodePudding user response:
This line is a problem
const storedTodos = localStorage.getItem(LOCAL_STORAGE_KEY);
you should parse the value before setting:
const storedTodos = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY))
CodePudding user response:
I haven't ran the code or tested anything but I think it's just the way your calling setTodos. Instead of passing in an anonymous function I would define the new todo list first, then use it to set the state. Try something like this.
function handleAddTodo(e) {
const name = todoNameRef.current.value;
if (name === '') return;
const newTodos = [...prevTodos, { id: v4(), name: name, complete: false }];
setTodos(newTodos);
todoNameRef.current.value = null;
}
You could probably get away with this too.
function handleAddTodo(e) {
const name = todoNameRef.current.value;
if (name === '') return;
setTodos([...prevTodos, { id: v4(), name: name, complete: false }]);
todoNameRef.current.value = null;
}
Hopefully that helps.