React中点击map渲染按钮如何更新对应对象points值并存入failedArr
实现方案
核心问题说明
你当前代码中的failedArr是组件每次渲染时临时生成的普通变量,没有通过useState托管,即使手动修改了它的值,既不会触发组件重新渲染展示最新结果,下次组件重渲染时也会被重置为初始值,这是无法实现更新的核心原因。
修改步骤
- 新增
failedArr对应的状态,用来托管数组数据,触发更新 - 将原来生成
failedArr的逻辑挪到useEffect中,接口返回数据处理完成后直接存入状态 - 实现点击加1的处理函数,通过唯一标识
name匹配对应对象,以不可变的方式更新points属性 - 给按钮绑定点击事件,传入当前项的
name作为匹配标识
完整修改后代码
import {fetchAll} from '../AppFetch'; import {useEffect, useState} from 'react'; export default function Subjects() { const [data, setData] = useState({}); // 新增状态托管failedArr const [failedArr, setFailedArr] = useState([]); useEffect(( ) => { fetchAll("http://localhost:3000/example.json", (res) => { setData(res); // 把生成failedArr的逻辑挪到这里,数据返回后处理并存入状态 const tempArr = []; for(let i=0; i<Object.entries(res).length; i++){ const status = Object.values(res)[i]; for(let j=0; j < Object.keys(status).length; j++){ const failed=Object.entries(status)[j][1] tempArr.push(failed[j]) } } setFailedArr(tempArr); }) }, []); // 实现点击加1的方法 const handleAddPoint = (subjectName) => { // 用不可变方式更新数组,避免直接修改原状态 setFailedArr(prevArr => prevArr.map(item => { if(item.name === subjectName) { // 匹配到对应项,返回新对象,points加1 return {...item, points: item.points + 1} } // 不匹配的项原样返回 return item; })) } return <div className="row"> {failedArr.map(key => ( <div key={key.name}> {/* 绑定点击事件,传入当前科目名称 */} <button onClick={() => handleAddPoint(key.name)}>Add point</button> <p>{key.name} - {key.points}</p> </div> ))} </div>; }
实现逻辑说明
- 更新状态时采用
setFailedArr的回调写法,能保证拿到的是最新的数组状态,避免闭包问题 - 匹配到目标对象时返回新对象,没有直接修改原数组或原对象,符合React状态不可变的更新原则,能正确触发组件重渲染
- 用科目
name作为唯一匹配标识,只会修改点击按钮对应的对象的points值
内容的提问来源于stack exchange,提问作者Egon Adelsberger
相关产品推荐
相关产品推荐

