React待办列表应用报错:Uncaught TypeError: prevTodos is not iterable
React待办列表应用:
Uncaught TypeError: prevTodos is not iterable 错误解决 问题场景
开发React待办列表应用时,点击添加待办项触发handleAddTodo函数,控制台抛出错误:
Uncaught TypeError: prevTodos is not iterable
相关处理代码:
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; }
完整应用代码:
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;
错误根源
- localStorage数据未解析:从
localStorage.getItem获取的是JSON格式字符串,直接赋值给状态todos会让其类型变为字符串,而字符串无法被...展开运算符迭代。 - 无效的状态重置:第一个
useEffect末尾调用了无参数的setTodos(),会将todos状态置为undefined,同样导致prevTodos不可迭代。
修复步骤
修改第一个useEffect的逻辑:
useEffect(() => { const storedTodos = localStorage.getItem(LOCAL_STORAGE_KEY); if (storedTodos) { // 将JSON字符串解析为数组类型 setTodos(JSON.parse(storedTodos)); } // 移除多余的setTodos()调用 }, []);
补充说明
- 始终确保
todos状态为数组类型,这样展开运算符和数组相关操作才能正常执行。 - 避免无参数调用
setTodos,这会破坏状态的预期结构,引发类型错误。
内容的提问来源于stack exchange,提问作者Gabriel Ogassawara
相关产品推荐
相关产品推荐

