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

React对象数组渲染异常:实际5个元素仅渲染3个,控制台长度显示不一致

问题根源与解决方案

我一眼就看出问题出在异步操作的处理顺序上,咱们来一步步拆解:

为什么会出现“控制台展开才看到5个元素”的情况?

你在handleSubmit里的执行逻辑有个关键漏洞:

  1. 先完成3个同步的错误检查(gamertag格式、邮箱格式、协议勾选),把错误放进totalErrors数组;
  2. 发起两个异步的fetch请求(检查邮箱和gamertag是否已存在);
  3. 立刻调用setErrors(totalErrors)更新状态。

但fetch是异步的!当你调用setErrors的时候,两个fetch的回调函数还没执行——这时候totalErrors里只有前面3个同步错误。等后续fetch完成后,你往totalErrors里push新错误,但这个数组已经是之前的旧数组了,而且你没有重新调用setErrors触发状态更新,所以React不会重新渲染组件。

至于控制台里“展开后显示5个元素”,是因为浏览器会实时展示数组的当前内存状态,但组件已经用了旧的state值来渲染,所以页面只显示3个。

修复方案:用Promise.all等待所有异步操作完成

我们需要等两个fetch都返回结果后,再把所有错误收集起来统一更新state。修改你的handleSubmit函数如下:

const handleSubmit = (event) => {
  event.preventDefault();
  let totalErrors = [];

  // 同步验证逻辑保持不变(修正了gamertag的错误文案)
  if (gamertag.length === 0 || gamertag.length > 30) {
    totalErrors.push({"error": "El gamertag debe tener entre 2 y 30 caracteres"});
  }
  if (!/^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/.test(mail)) {
    totalErrors.push({"error": "Introduce un correo válido"});
  }
  if (!isChecked) {
    totalErrors.push({"error": "Debes aceptar haber leído las políticas para poder registrarte"});
  }
  // 新增:验证两次密码是否一致
  if (password !== repassword) {
    totalErrors.push({"error": "Las contraseñas no coinciden"});
  }

  // 用Promise.all等待两个异步请求完成
  Promise.all([
    fetch("URL API" + mail).then(response => response.json()),
    fetch("URL API" + gamertag).then(response => response.json())
  ])
  .then(([mailCheckData, gamertagCheckData]) => {
    // 处理异步返回的错误
    if (mailCheckData.length > 0) {
      totalErrors.push({"error": "Ya hay una cuenta con este correo"});
    }
    if (gamertagCheckData.length > 0) {
      totalErrors.push({"error": "El gamertag ya ha sido usado por otro usuario"});
    }
    // 现在统一更新state,确保所有错误都被包含
    setErrors(totalErrors);
  })
  .catch(() => {
    // 处理网络请求失败的情况
    totalErrors.push({"error": "Error al verificar tus datos, por favor intenta de nuevo"});
    setErrors(totalErrors);
  });
}

额外的优化建议

  • 不要用index作为列表的key:虽然错误列表不会频繁排序,但最好用错误内容本身作为key(比如key={item.error}),避免React渲染时出现不必要的问题;
  • 补上两次密码一致性的验证:你之前的代码里没检查password和repassword是否相同,我已经在上面的代码里补上了;
  • 可以给异步请求加loading状态:避免用户重复提交,提升体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:32:39