React.js POST提交数据成功后表格未更新,如何正确使用useEffect实现同步?
问题根因
你的useEffect逻辑本身没有错误,出现新增数据不刷新的核心原因是两个:
- Table组件的useEffect依赖项为空数组,只会在组件首次挂载时执行1次拉取逻辑,后续后端数据更新后不会自动重新调用接口拉取最新数据
- AddForm和Table是两个独立组件,提交成功后没有通知Table刷新数据的机制
另外你现有代码还存在一个隐藏问题:Table中渲染列表的key直接用了post对象,不符合React要求key为唯一基本类型值的规范,后续会引发渲染异常。
解决方案(改动最小,适合初学者)
采用状态提升+回调通知的方案实现数据同步,需要修改3处代码:
1. 修改Table组件
- 新增
refreshTriggerprop作为useEffect的依赖项,每次该值变化就重新拉取数据 - 修正列表key为后端返回的唯一id
import React, { useState, useEffect } from "react"; import axios from "axios"; // 新增入参refreshTrigger const Table = ({ refreshTrigger }) => { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { const fetchPosts = async () => { setLoading(true); const res = await axios.get("http://localhost:3000/movies"); setPosts(res.data); setLoading(false); }; fetchPosts(); }, [refreshTrigger]); // 依赖改为refreshTrigger,变化即重新拉取 // 排序逻辑不变 const [order, setOrder] = useState("ascending"); const sorting = (s) => { if (order === "ascending") { const sorted = [...posts].sort((a, b) => a[s].toLowerCase() > b[s].toLowerCase() ? 1 : -1 ); setPosts(sorted); setOrder("descending"); } if (order === "descending") { const sorted = [...posts].sort((a, b) => a[s].toLowerCase() < b[s].toLowerCase() ? 1 : -1 ); setPosts(sorted); setOrder("ascending"); } }; return ( <div className="container"> <table className="table table-bordered table-striped"> <thead> <tr> <th className="click" onClick={() => sorting("name")}>Name</th> <th>Genre</th> <th>Rating</th> <th>Action</th> </tr> </thead> <tbody> {/* key改为post.id,不要用post对象 */} {posts.map((post) => ( <tr key={post.id}> <td>{post.name}</td> <td>{post.genre}</td> <td>{post.rating}</td> <td> <button className="btn btn-outline-success">delete</button> <button className="btn btn-outline-warning">edit</button> </td> </tr> ))} </tbody> </table> </div> ); }; export default Table;
2. 修改AddForm组件
- 新增
onSubmitSuccess回调prop,提交成功后触发该回调通知父组件 - 把
e.preventDefault()移到逻辑最前面,避免异常时触发表单默认提交 - 可选新增提交成功后清空表单的逻辑
import React, { useState } from "react"; // 新增入参onSubmitSuccess function AddForm({ onSubmitSuccess }) { const [name, setName] = useState(""); const [genre, setGenre] = useState(""); const [rating, setRating] = useState(""); const handleSubmit = (e) => { e.preventDefault(); // 移到最前面 fetch("http://localhost:3000/movies", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name, genre, rating }), }) .then((response) => response.json()) .then((response) => { console.log(response); // 提交成功触发回调 onSubmitSuccess?.(); // 清空表单 setName(""); setGenre(""); setRating(""); }); }; return ( <div className="text-center"> <h2>Add a New movie</h2> <form onSubmit={handleSubmit}> <label>Name:</label> <input name="name" type="text" required value={name} onChange={(e) => setName(e.target.value)} /> <label>Genre:</label> <input name="genre" type="text" required value={genre} onChange={(e) => setGenre(e.target.value)} /> <label>Rating:</label> <input name="rating" type="text" required value={rating} onChange={(e) => setRating(e.target.value)} /> <button type="submit">Add</button> </form> </div> ); } export default AddForm;
3. 修改两个组件的共同父组件(一般是App.jsx)
维护一个刷新触发器状态,收到AddForm的提交成功通知后更新触发器,触发Table重新拉取数据
import { useState } from "react"; import Table from "./Table"; import AddForm from "./AddForm"; function App() { // 刷新触发器,数值变化即代表需要刷新表格 const [refreshTrigger, setRefreshTrigger] = useState(0); const handleAddSuccess = () => { // 数值+1触发变化 setRefreshTrigger(prev => prev + 1); }; return ( <div> <AddForm onSubmitSuccess={handleAddSuccess} /> <Table refreshTrigger={refreshTrigger} /> </div> ); } export default App;
内容的提问来源于stack exchange,提问作者vyperpunk
相关产品推荐
相关产品推荐

