向json-server插入数据后React UI/DOM未自动更新问题排查
React + Axios 插入数据后联系人列表不更新的问题
向json-server插入数据成功,但React页面的联系人列表并未立即更新,数据插入功能正常,但UI无变化。以下是相关代码:
App.js
import Axios from "axios"; import React, { useEffect, useState } from "react"; import Add__Contact from "./api/Add__Contact"; const App = () => { const [name, setName] = useState(""); const [phone, setPhone] = useState(""); const [contacts, setContacts] = useState([]); const url = "http://localhost:3006/contacts"; //get all availbale contacts useEffect(() => { // get all contacts async async function getUsers() { Axios.get(url).then((response) => { setContacts(response.data); }); } getUsers(); console.log(contacts); // get all contacts non-async // Axios.get(url).then((response) => { // setContacts(response.data); // }); }, []); //add new contact to server const addContact = () => { const saveRes = Add__Contact({ name, phone }); }; // view return ( <div> <h4>Add contact</h4> <div> <input type="text" name="name" value={name} onChange={(e) => setName(e.target.value)} placeholder="name here" /> <br /> <br /> <input type="text" name="phone" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="Phone here" /> <br /> <br /> <button onClick={addContact}>Add to Contact</button> </div> <hr /> <h4>List of Contacts</h4> <div> {contacts.map((contact) => { return ( <div key={contact.id}> <span>{contact.name} : </span> <span> {contact.phone}</span> </div> ); })} </div> </div> ); }; export default App;
Add__Contact.js
import Axios from "axios"; const Add__Contact = async ({ name, phone }) => { Axios({ method: "post", url: "http://localhost:3006/contacts", headers: { "Content-Type": "application/json", }, data: { name, phone, }, }).then(function (res) { // console.log(res); }); }; export default Add__Contact;
db.json
{ "contacts": [ { "name": "Max", "phone": "123456", "id": 1 }, { "name": "John", "phone": "13454", "id": 2 }, { "name": "Candy", "phone": "1245781245", "id": 3 } ] }
问题原因
你的useEffect依赖项是空数组[],这意味着它只会在组件首次挂载时执行一次,后续不管任何状态变化都不会重新触发。所以调用Add__Contact插入数据后,并不会重新拉取联系人列表,自然UI不会更新。另外,Add__Contact是异步函数,但你调用它时未处理异步结果,也没有在插入成功后更新本地状态。
修复方案
方式一:插入成功后重新拉取联系人列表
把获取联系人的逻辑抽成独立函数,在插入完成后重新调用:
const App = () => { const [name, setName] = useState(""); const [phone, setPhone] = useState(""); const [contacts, setContacts] = useState([]); const url = "http://localhost:3006/contacts"; // 抽成独立复用的函数 const fetchContacts = async () => { const response = await Axios.get(url); setContacts(response.data); }; // 首次挂载时获取列表 useEffect(() => { fetchContacts(); }, []); const addContact = async () => { // 等待插入请求完成 await Add__Contact({ name, phone }); // 重新拉取最新列表 fetchContacts(); // 清空输入框 setName(""); setPhone(""); }; // ... 原有渲染逻辑不变 };
同时修改Add__Contact确保返回Promise:
const Add__Contact = async ({ name, phone }) => { // 返回Axios请求的Promise,方便外部await return Axios({ method: "post", url: "http://localhost:3006/contacts", headers: { "Content-Type": "application/json", }, data: { name, phone, }, }); };
方式二:插入成功后直接更新本地状态(无需重新请求)
如果json-server返回了插入的完整联系人数据(包括自动生成的id),可以直接把新数据加到本地列表,减少一次网络请求:
const addContact = async () => { const response = await Add__Contact({ name, phone }); // 用函数式更新确保拿到最新的状态 setContacts(prevContacts => [...prevContacts, response.data]); // 清空输入框 setName(""); setPhone(""); };
额外提示
- 不要在
useEffect里直接打印contacts,因为setContacts是异步操作,打印的会是旧值。如果要查看更新后的状态,可以新增一个监听contacts的useEffect:
useEffect(() => { console.log(contacts); }, [contacts]);
内容的提问来源于stack exchange,提问作者unReact
相关产品推荐
相关产品推荐

