You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React setState更新数组后map渲染的TextField无法正常重渲染问题

问题原因

  • 违反React状态不可变规则:你直接修改了原有franchises数组的内部属性,再将原数组引用传入setFranchises,React做状态浅比较时会判定状态无变化,不会触发完整重渲染。同时闭包会缓存上一次渲染的旧franchises值,导致每次输入都是在旧值基础上修改,最终表现为输入仅单个字符生效。
  • 列表渲染未加唯一key:遍历franchises渲染商户组件时没有设置唯一key属性,React的diff算法无法正确识别列表项的更新,也会导致渲染异常。
  • FixableTextField属性写法存在隐患:你在TextField组件中先定义了value={props.restAddress}再展开props,虽然当前场景下父组件传入的value会覆盖该错误值,但该写法容易出现字段赋值错乱。

修正代码

1. 修正MyPage中onChange的状态更新逻辑

onChange={(e) => {
  const newValue = e.target.value
  // 生成全新的数组,完全不修改原有状态
  const newFranchises = franchises.map((item, index) => {
    if (index === i) {
      // 对应下标的对象也做浅拷贝
      return {
        ...item,
        data: {
          ...item.data,
          storeName: newValue
        }
      }
    }
    return item
  })
  setFranchises(newFranchises)
}}

2. 给列表项添加唯一key

{franchises && franchises.map((v, i) => {
  // 优先用商户的唯一id作为key,没有的话暂时用index兜底
  return (<React.Fragment key={v.id || i}>
    {/* 原有FixableTextField、AddressForm组件逻辑保持不变 */}
  </React.Fragment>)
})}

3. 修正FixableTextField的属性写法

删除TextField上多余的value={props.restAddress},避免赋值冲突:

<TextField
  variant="outlined"
  disabled={!fixable}
  {...props}
  style={{
    margin: `${marginTop}px ${marginSide}px`,
    width: `calc(100% - ${marginSide * 2}px)`
  }}
></TextField>

如果确实需要兼容restAddress字段,调整属性顺序明确优先级:

<TextField
  variant="outlined"
  disabled={!fixable}
  {...props}
  // 固定属性放在展开props之后,避免被传入的props覆盖
  value={props.restAddress || props.value}
  style={{
    margin: `${marginTop}px ${marginSide}px`,
    width: `calc(100% - ${marginSide * 2}px)`
  }}
></TextField>

内容的提问来源于stack exchange,提问作者Janghyup Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 01:48:03