You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:56:00