React状态中对象数组属性更新后未触发渲染的问题解决
React状态更新后组件不渲染的解决方法
你的代码中状态更新逻辑本身是正确的,问题出在渲染环节和表单按钮的默认行为上,具体修正点如下:
1. 修复map函数的返回值
在渲染components列表时,map回调函数没有返回JSX元素。你用了大括号包裹逻辑,但未显式return,导致map返回的是全为undefined的数组,无法渲染列表项。
错误代码:
{system.components.map((c, idx) => { <li key={idx}>Component: {c.name}</li> })}
修正后(两种方式任选其一):
- 去掉大括号,用箭头函数隐式返回:
{system.components.map((c, idx) => ( <li key={idx}>Component: {c.name}</li> ))}
- 保留大括号,添加显式return:
{system.components.map((c, idx) => { return <li key={idx}>Component: {c.name}</li> })}
2. 阻止按钮默认的表单提交行为
添加组件的按钮默认是submit类型,点击会触发表单提交,导致页面刷新、状态重置。需要给按钮加上type="button":
修正后的按钮代码:
<button type="button" onClick={() => addComponent()} > + Add Component </button>
3. 规范变量声明
defaultComponent未用const声明,属于全局变量,建议改为局部常量:
const defaultComponent = { name: "C1", comment: "", }
完整修正后的代码
import React, { useState } from "react"; import "./styles.css"; const defaultComponent = { name: "C1", comment: "", }; export default function App() { const [system, setSystem] = useState({ name: "", price: 0.0, components: [], }); function modifySystemProperty(property, newValue) { let modifiedSystem = { ...system }; modifiedSystem[property] = newValue; setSystem(modifiedSystem); } function addComponent() { setSystem((system) => ({ ...system, components: [...system.components, defaultComponent], })); } return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h3>Edit system:</h3> <form> <div> <label htmlFor="form-name">Name: </label> <input id="form-name" type="text" value={system?.name} onChange={(e) => modifySystemProperty("name", e.target.value)} /> </div> <div> <label htmlFor="form-price">Price: </label> <input id="form-price" type="number" min="0" step="0.1" value={system?.price} onChange={(e) => modifySystemProperty("price", +e.target.value)} /> </div> <div> <p>Components:</p> <ul> {system.components.map((c, idx) => ( <li key={idx}>Component: {c.name}</li> ))} </ul> <button type="button" onClick={() => addComponent()} > + Add Component </button> </div> </form> </div> ); }
说明:你原本的addComponent函数使用了函数式更新和扩展运算符,已经正确遵循了React状态不可变的原则,状态更新逻辑没有问题,之前的组件未渲染是因为上述两个渲染环节的错误导致的。
内容的提问来源于stack exchange,提问作者Romn
相关产品推荐
相关产品推荐

