React中PUT请求更新数据后需刷新浏览器显示的问题咨询
问题
背景说明
在通讯录应用中,用户输入name和number并点击add按钮后,新联系人信息会自动添加至数据库。若name已存在,前端App.js会弹出提示:[name] 已存在于通讯录中,是否继续更新为新号码?
问题描述
点击add按钮执行更新操作后,数据库数据已成功更新,但必须刷新浏览器才能在页面看到正确的新号码(更新后未刷新显示旧号码,刷新后显示新号码)。请问该现象是否属于正常表现?
相关代码
App.js
const addName = (event) => { event.preventDefault() const nameObject = { name: newName, number: newNumber } const changeNumberText = 'is already exist in phonebook, continue to update with new number ?' const existingPerson = persons.find(person => person.name.toLowerCase() === nameObject.name.toLowerCase()) const newPerson = {...existingPerson, number: newNumber} if (existingPerson && window.confirm(`${existingPerson.name} ${changeNumberText}`)) { personService .update(existingPerson.id, newPerson) .then(response => { setPersons(persons.map(person=>person.id === existingPerson.id ? response : person)) setNewName('') setNewNumber('') setErrorMessage( `${existingPerson.name}'s phone number has been updated` ) setTimeout(() => { setErrorMessage(null) }, 5000) }) } else if(!existingPerson) { personService
Person.js
import React from "react"; const Person = ({person, deleteButton, text}) => { return ( <div> <li className='personinfo'> {person.name} {person.number} <button onClick={deleteButton}> {text} </button> </li> </div> ); } export default Person
渲染代码
<ul> {persons.filter((person) => { if (searchTerm === "") { return person } else if (person.name.toLowerCase().includes(searchTerm.toLowerCase())) { return person } }).map((person, id) => { return ( <Person key={id} person={person} deleteButton={()=>handleDelete(person.id)} text='Delete' /> ); }) } </ul>
补充信息
接口返回的response包含更新后的正确联系人数据。
回答
这种现象完全不属于正常表现,React应用应该在状态更新后自动触发视图重渲染,无需手动刷新浏览器。
问题根源在于渲染时的key设置错误:
你在映射渲染Person组件时,使用了数组的索引id作为key。当数组中已有项的内容更新但位置未变时,React会基于key判断组件未发生变化,从而复用旧组件实例,不会重新渲染该联系人的信息,导致页面显示旧数据。
修复方案
将渲染代码中的key替换为联系人的唯一id,让React能精准识别出哪一项数据发生了变化,从而触发对应组件的重渲染:
<ul> {persons.filter((person) => { if (searchTerm === "") { return person } else if (person.name.toLowerCase().includes(searchTerm.toLowerCase())) { return person } }).map((person) => { return ( <Person key={person.id} person={person} deleteButton={()=>handleDelete(person.id)} text='Delete' /> ); }) } </ul>
额外验证:可以在setPersons后添加日志,打印更新后的persons状态,确认新数据已正确存入状态。如果状态更新正确但视图未刷新,那必然是key的问题。修改完成后,更新操作结束后页面会自动显示最新号码,无需手动刷新。
内容的提问来源于stack exchange,提问作者Jabri Juhinin
相关产品推荐
相关产品推荐

