React修改props值后子组件点赞数不自动更新需刷新才生效
问题原因
你遇到的视图不更新问题核心是违反了React的状态更新规则:
- React通过浅比较状态/Props的引用地址判断是否需要触发组件重渲染
- 你当前的
updateLike方法直接修改vacation对象的likes属性,没有改变vacation对象本身的引用地址,React检测不到数据变化,因此不会触发子组件重渲染,只有手动刷新页面才能读取到修改后的值 - 你之前尝试
useEffect不生效也是同理,依赖的对象引用没有变化,副作用自然不会触发。
修复方法
核心原则:所有对象、数组类型的React状态更新,必须返回全新的引用,禁止直接修改原状态的属性。
1. 重写App.js中的updateLike方法
根据你存储度假数据的方式选择对应写法:
场景1:所有度假数据存在数组状态中(常见列表场景)
假设你在App中用如下方式存储数据:const [vacations, setVacations] = useState(/* 初始度假列表数据 */),将updateLike修改为:
function updateLike(targetVacation, update) { // 传入状态更新函数,基于前值生成新状态 setVacations(prevList => { // map会返回全新的数组,产生新的引用 return prevList.map(item => { // 用唯一标识(比如id)匹配当前操作的度假项,不要直接改传入的targetVacation if (item.id === targetVacation.id) { // 展开原对象生成新副本,只修改需要更新的likes字段 return { ...item, likes: update === 1 ? item.likes + 1 : item.likes - 1 } } return item }) }) }
场景2:当前展示的单个vacation是独立状态
如果App中是单独存储当前打开的度假项:const [vacation, setVacation] = useState(/* 当前选中的度假项 */),可以简化逻辑,不需要把vacation作为参数传回:
// 方法只需要接收更新类型参数即可 function updateLike(update) { setVacation(prev => ({ ...prev, likes: update === 1 ? prev.likes + 1 : prev.likes - 1 })) }
对应子组件的点赞点击事件修改为:
<p onClick={() => updateLike(1)} className="likes__add"> <FontAwesomeIcon icon={faHeart} />{vacation.likes} </p>
2. 校验点
修改完成后点击点赞按钮,状态更新会产生新的对象/数组引用,React检测到props变化后会自动触发子组件重渲染,不需要手动刷新页面,也不需要额外加useEffect监听处理。
提示:不要直接修改props传入的对象值,所有数据修改都要通过父组件的状态更新方法完成,保证数据流单向可控。
内容的提问来源于stack exchange,提问作者Senna Oudshoorn
相关产品推荐
相关产品推荐

