React使用prevState修改数组对象boolean值后无法触发重渲染求助
问题根因
React的状态更新是基于引用比较的,你在setObj的回调里直接修改了原数组prev内部的对象属性,最后返回的还是原来的数组引用,React检测到引用没有变化,就会跳过重渲染,所以你看不到界面更新。
另外你代码里的window.alert拿不到最新的obj值,是因为React的状态更新是异步的,调用setObj后状态不会立刻变更,同步代码里访问的还是更新前的旧值。
修正方案
修改handleClick的逻辑,创建新的数组副本、同时要修改的对象也要创建新副本,保证返回的状态是全新的引用:
const handleClick = (e) => { const idx = Number(e.target.value); // e.target.value默认是字符串类型,需要转成数字匹配索引 setObj(prev => { // 创建全新的数组副本 const newArr = [...prev]; // 创建要修改的对象的副本,再更新boolean值,避免修改原状态对象 newArr[idx] = { ...newArr[idx], boolean: !newArr[idx].boolean }; return newArr; }); }
另外还有两个可以优化的细节:
- 列表渲染的
key属性不要直接用数组索引,最好用每一项唯一的字段比如name,避免数组顺序变化后出现渲染异常 img标签的alt属性你写的map.key是不存在的,改成map.name更合理
完整修正后代码
import { useState } from 'react'; // 注意替换为你实际的图片引入路径 import img from './你的图片路径'; export default function App() { const [obj, setObj] = useState([ { name: "chicken", comments: "nice", photo: img, boolean: false }, { name: "beef", comments: "ehh", photo: img, boolean: false }, { name: "turkey", comments: "not bad", photo: img, boolean: false }, { name: "broccoli", comments: "cool", photo: img, boolean: false }, { name: "carrot", comments: "disgusting", photo: img, boolean: false } ]); const handleClick = (e) => { const idx = Number(e.target.value); setObj(prev => { const newArr = [...prev]; newArr[idx] = { ...newArr[idx], boolean: !newArr[idx].boolean }; return newArr; }); } return ( <div> {obj.map((item, index) => ( <div key={item.name}> <img src={item.photo} alt={item.name} /> <h1>{item.name}</h1> <p>{`${item.boolean}`}</p> <p>{index}</p> <button value={index} onClick={handleClick}> show comments </button> {/* 可直接加这行实现点击展示评论的效果 */} {item.boolean && <p>评论:{item.comments}</p>} </div> ))} </div> ); }
内容的提问来源于stack exchange,提问作者Ahmet Ulutaş
相关产品推荐
相关产品推荐

