React中修改数组对象添加属性后页面未重新渲染问题求助
问题原因
该问题本质就是React响应式更新规则相关的问题,你当前的判断有误。
你定义的labelsArray是组件外部的普通JavaScript变量,不属于React管控的响应式状态,React不会监听这类普通变量的变更,也不会因为变量值变化触发组件重渲染,因此才会出现控制台打印数组已更新、但UI毫无变化的情况。
另外你当前的更新写法属于直接修改原对象的突变操作,就算后续把数组改为state,这种写法也会因为React对state做浅比较时检测不到引用变化,依然无法触发重渲染。
修复方案
按照以下步骤修改代码即可实现预期效果:
- 删除组件外部的
labelsArray定义,将其移入组件内部用useState声明为响应式状态 - 将
appendLabel方法移入组件内部,更新状态时生成全新的数组和对象引用,避免直接修改原状态 - 修正map遍历的key值,不要直接用对象本身作为key,改用唯一固定的属性值,避免渲染异常
修复后的核心代码片段
const Checklist = ({ classes,activeStep }) => { // 声明为响应式状态 const [labelsArray, setLabelsArray] = useState([ { label: 'Random text?', sublabel1: 'Lorem Ipsum' }, { label: 'Another random text', sublabel1: 'Hello World' }, { label: 'Cool', sublabel1: 'cool', sublabel2: 'ayo' } ]); const appendLabel = () => { setLabelsArray(prev => { // 拷贝原数组生成新引用 const newArray = [...prev]; // 拷贝目标对象追加新属性,不修改原对象 newArray[1] = { ...newArray[1], warningLabel: "Hello", errorLabel: "Hello" }; return newArray; }) }; return ( <React.Fragment> <Stepper alternativeLabel activeStep={2} connector={<StepConnector />} className={classes.stepper}> {/* 修正key为唯一固定的label文本 */} {labelsArray.map(label => ( <Step key={label.label} completed> <StepLabel active completed StepIconProps={{ classes: { root: classes.step, completed: classes.completed, active: classes.active, disabled: classes.disabled } }}> <div className={classes.stepLabelRoot}> <span className={classes.label}> {label.label} </span> <span className={classes.sublabel}> {label.sublabel1} </span> <span className={classes.sublabel}> {label.sublabel2} </span> <span className={classes.sublabel}> {label.sublabel3} </span> <span className={classes.errorLabel}> {label.errorLabel && <img src="/static/images/lock-material.png" alt="img" style={{ height: '15px', width: '15px' }} />} {label.errorLabel} </span> <span className={classes.warningLabel}> {label.warningLabel && <img src="/static/images/warning-sign.png" alt="img" style={{ height: '15px', width: '15px' }} />} {label.warningLabel} </span> </div> </StepLabel> </Step> ))} </Stepper> <Button onClick={appendLabel}>Hello</Button> </React.Fragment> ); };
其余样式定义、props校验、导出逻辑保持原有写法不变即可。
内容的提问来源于stack exchange,提问作者Kenny Quach
相关产品推荐
相关产品推荐

