ReactJS Todo应用添加待办后需刷新才更新列表的问题求助
解决Todo添加后列表需刷新才更新的问题
你的问题核心是:InputTodo组件提交新待办后,没有触发ListTodos组件更新数据——因为ListTodos仅在组件挂载时调用一次getTodos,后续没有重新获取数据的触发逻辑。下面提供两种可行的解决方法:
方案一:状态提升到父组件(React 标准状态共享方式)
将todos状态和getTodos方法移到共同的父组件(比如App.js),通过 props 传递给子组件,在添加/删除/编辑操作完成后主动调用getTodos刷新列表。
1. 修改父组件 App.js
import React, { Fragment, useEffect, useState } from "react"; import InputTodo from "./InputTodo"; import ListTodos from "./ListTodos"; function App() { const [todos, setTodos] = useState([]); const getTodos = async () => { try { const response = await fetch("http://localhost:5000/todos"); const jsonData = await response.json(); setTodos(jsonData); } catch (err) { console.error(err.message); } }; useEffect(() => { getTodos(); }, []); return ( <Fragment> <div className="container"> <InputTodo getTodos={getTodos} /> <ListTodos todos={todos} setTodos={setTodos} getTodos={getTodos} /> </div> </Fragment> ); } export default App;
2. 修改 InputTodo.js
提交成功后调用父组件传递的getTodos刷新列表,并清空输入框:
import React, { Fragment, useState } from "react"; const InputTodo = ({ getTodos }) => { const [description, setDescription] = useState(""); const onSubmitForm = async (e) => { e.preventDefault(); try { const body = { description }; await fetch("http://localhost:5000/todos", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), }); // 刷新列表 getTodos(); // 清空输入框 setDescription(""); } catch (err) { console.error(err.message); } }; return ( <Fragment> <h1 className="text-center mt-5">Input Todo</h1> <form className="d-flex mt-5" onSubmit={onSubmitForm}> <input type="text" className="form-control" value={description} onChange={(e) => setDescription(e.target.value)} /> <button className="btn btn-success" type="submit"> Add </button> </form> </Fragment> ); }; export default InputTodo;
3. 修改 ListTodos.js
接收父组件的状态和方法,删除操作后也可选择调用getTodos刷新:
import React, { Fragment } from "react"; import EditTodo from "./EditTodo"; const ListTodos = ({ todos, setTodos, getTodos }) => { const deleteTodo = async (id) => { try { await fetch(`http://localhost:5000/todos/${id}`, { method: "DELETE", }); // 两种方式二选一:直接过滤现有列表 或 重新获取数据 // setTodos(todos.filter((todo) => todo.todo_id !== id)); getTodos(); } catch (err) { console.error(err.message); } }; return ( <Fragment> <table className="table mt-5 text-center"> <thead> <tr> <th>Description</th> <th>Edit</th> <th>Delete</th> </tr> </thead> <tbody> {todos.map((todo) => ( <tr key={todo.todo_id}> <td>{todo.description}</td> <td> <EditTodo todo={todo} getTodos={getTodos} /> </td> <td> <button className="btn btn-danger" onClick={() => deleteTodo(todo.todo_id)} > Delete </button> </td> </tr> ))} </tbody> </table> </Fragment> ); }; export default ListTodos;
4. 同步修改 EditTodo 组件
确保编辑完成后也调用getTodos刷新列表,逻辑和InputTodo类似。
方案二:返回新创建的 Todo 并直接更新列表(性能更优)
修改后端 POST API,让它返回刚创建的 Todo 数据,前端直接将新 Todo 添加到现有列表,避免重新请求所有数据。
1. 修改后端 POST API
app.post("/todos", async (req, res) => { try { const { description } = req.body; // 使用 RETURNING * 返回新插入的行 const newTodo = await pool.query( "INSERT INTO todo (description) VALUES ($1) RETURNING *", [description] ); res.json(newTodo.rows[0]); } catch (err) { console.error(err.message); } });
2. 修改 InputTodo.js(配合状态提升)
const onSubmitForm = async (e) => { e.preventDefault(); try { const body = { description }; const response = await fetch("http://localhost:5000/todos", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), }); const newTodo = await response.json(); // 直接将新 Todo 添加到列表 setTodos(prevTodos => [...prevTodos, newTodo]); setDescription(""); } catch (err) { console.error(err.message); } };
这种方式减少了一次 GET 请求,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者Shahzaib Mirza
相关产品推荐
相关产品推荐

