React 子向父级组件通信时,state为旧的数据

2023-11-06

问题描述

当嵌套太深的子组件触发更新父组件时,父组件获取到的state(map传入子组件)是旧的

问题场景

初始子组件仅为1个Input输入框:
在这里插入图片描述
新增后有2个Input输入框:
在这里插入图片描述
此时触发222输入框的修改,通知上级组件保存修改的内容时,父组件存储两个Input输入框的State:list,打印出来是旧的!
在这里插入图片描述
触发444输入框的修改,打印list:
在这里插入图片描述
具体看源码如下:

问题代码

父组件

// 父组件
const Parent = () => {
  const [list, setList] = useState([]);

  //模拟拉取数据
  useEffect(() => {
    setList([
      {
        name: 111,
        subList: [
          {
            value: 222,
          },
        ],
      },
    ]);
  }, []);

  const onChildChange = (value) => {
    console.log('子组件触发更新,此时的list:', list);
  };

  const handleAddList = () => {
    const newList = [
      ...list,
      {
        name: 333,
        subList: [
          {
            value: 444,
          },
        ],
      },
    ];
    setList(newList);
  };

  return (
	<>
	{list.length > 0 && (
        list.map(item => (
          <Children key={item.name} value={item.subList} onChange={onChildChange} />
        ))
      )}
      <Button onClick={handleAddList}>新增</Button>
	</>
	)
}

子组件

const Children = ({
  value,
  onChange,
}) => {
  const [subList, setSubList] = useState([]);

  useEffect(() => {
    setSubList([...value]);
  }, [value]);

  const handleChange = (e) => {
    onChange(e.target.value);
  };

  const columns = useMemo(() => [
    {
      render: (text: string, item, index) => (
        <Input value={item.value} onChange={handleChange} />
      ),
    },
  ], [subList]);

  return (
    <>
      {subList.length > 0 && (
        <Table
          rowKey="value"
          columns={columns}
          showHeader={false}
          dataSource={subList}
          className={s.mountsWrapper}
          pagination={false}
        />
      )}
    </>
  );
};

问题分析

由于子组件又使用Table渲染导致嵌套过深,传入子组件的props:

<Children value={item.subList} onChange={onChildChange} />

item是list的子项,子组件仅收到item.subList的prop,当list新增第二个输入框时,子组件调用onChange的箭头函数内,上下文查到的list是旧的。

解决办法1

props传参尽量选择传入state,比如这里的list:

<Children parentList={list} pIndex={index} onChange={onChildChange} />

只需要继续在子组件内通过pIndex即可找到原本需要传入的item

当父级list变化时,子组件也能及时更新触发onChange时的list

解决办法2

不使用Table渲染子组件数据(目测正常,但是原理不能弄明白)

const Children = ({
  value,
  onChange,
}) => {
  const [subList, setSubList] = useState([]);

  useEffect(() => {
    setSubList([...value]);
  }, [value]);

  const handleChange = (e) => {
    onChange(e.target.value);
  };

  return (
    <>
      {subList.length > 0 && (
        subList.map(item => (
          <Input key={item.value} value={item.value} onChange={handleChange} />
        ))
      )}
    </>
  );
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React 子向父级组件通信时,state为旧的数据 的相关文章

  • Exceljs:迭代每行和每列的每个单元格

    我想在所有单元格中添加粗边框 这是一个有角度的项目 我正在使用打字稿 我可以为 1 个单元格做到这一点 worksheet getCell A1 border top style thick left style thick bottom
  • ScrollTop 在 Chrome/Safari 中不起作用

    我的网站上有一个循环内的表单 当有人提交表单时 查询字符串会添加到 URL 中 例如 updated 111 然后 我的 JQuery 脚本检查数字的 url 并在提交表单并重新加载页面后滚动到该 div 该脚本在 Firefox 中运行良
  • 使用 Javascript 实现 Tinder 风格的拖放手势?

    我正在尝试找出哪些库可以用于仅使用 Javascript 的 Tinder 风格拖放手势 需要创建一个响应拖动手势的 HTML 元素 触摸并按住时 允许元素跟随用户的手指移动 当用户移开手指时 该元素会 动画回到原来的位置 如果元素在释放时
  • MUI 组件上的渐变边框

    我没能找到相当于border image source css 我的目标是在按钮组件上渲染边框渐变 这是添加渐变边框的方法button成分 V5 const options shouldForwardProp prop gt prop gr
  • 如何根据另一个动态下拉列表的值创建动态下拉列表?

    我有一个下拉菜单 当我选择一个选项时 它会创建一个动态下拉菜单 到目前为止 一切都很好 但我想创建另一个动态下拉列表 现在基于另一个动态下拉列表的值 我该怎么做 第一个动态下拉列表有效 我猜第二个无效 因为动态变量 div 没有静态 ID
  • 为什么我的箭头函数有原型属性?

    正如文档中提到的https developer mozilla org en docs Web JavaScript Reference Functions Arrow functions https developer mozilla o
  • 将 javascript 放在 header 之外有多糟糕?

    这个问题几乎已经说明了一切 我开始添加一些功能到我的周末项目 http www my clock net 对于我和几个朋友来说 这是一个小应用程序 因为我们是交换生 所以它对我们来说有点有用 但事情是这样的 我在 php 中执行此操作并使用
  • 内联执行生成的汇编程序

    我正在阅读以下演示文稿 http wingolog org pub qc 2012 js slides pdf http wingolog org pub qc 2012 js slides pdf其中讨论了 4 10 19 内联 ASM
  • 从对象获取数据 - 我看到数据但无法保存它们

    正如你所看到的 我是新来的 我确实尝试过搜索 但没有找到解决我问题的方法 所以这是我的问题 如果我这样做 console log grid data kendoGrid data 这在控制台中显示如下 所以我明白这一点 有一个数组和一个带有
  • 它们是“相同的”吗?代码大战

    这是完整的问题描述 给定两个数组 a 和 b 编写一个函数 comp a b Clojure 中的 compSame a b 来检查这两个数组是否具有 相同 元素以及相同的重数 这里 相同 意味着 b 中的元素是 a 平方中的元素 无论顺序
  • 单击时突出显示文本(javascript jquery html)

    当您在所有浏览器中双击某个单词时 它们会自动突出显示单击下的单词 但是否有可能找到一种方法exact单击一下就会发生同样的事情吗 我想这涉及到的事情可能是 TextRange 的东西 对所有段落 或整个正文或 div 的 onclick 做
  • 如何将输入字段值作为 URL 查询字符串传递,单击提交按钮将打开该字符串?

    我必须输入这样的字段
  • 调用不带括号的 javascript 函数

    以下 renderChat 函数用于将消息和图像渲染到聊天板上 该函数内部还有另一个函数 var onComplete function 它完成创建列表元素并将其附加到聊天列表的所有工作 onComplete函数之后就只有这三行代码 img
  • Bootstrap 3 - 模态背景不会根据模态对话框的高度调整大小?

    我将一个表单放入模式中 并尝试在用户触发单选按钮时显示表单的一些隐藏字段 显示隐藏字段后 模态自动重新缩放的高度 但模态背景的高度不能用作模态对话框 我该如何解决它 div class modal fade div class modal
  • jQuery 单击附加元素不起作用

    我有一个数组 我正在从 Array 获取数据并在 jQuery Append to list 中使用它 但是当我单击列表项时 它只显示最后一个元素 var array 1 2 7 3 4 8 5 6 9 for var i 0 i lt a
  • onClick 事件适用于触摸屏设备上的触摸吗?

    我用过onclick我的网站上的活动 但是 当我在谷歌浏览器的开发人员模式移动视图中打开它时 触摸使用鼠标单击的元素没有任何反应 所以我的问题是 我还必须添加吗ontouch事件连同onclick事件或 onClick 事件适用于所有触摸屏
  • .parents() 没有 jquery - 或 querySelectorAll 为父母[重复]

    这个问题在这里已经有答案了 可能的重复 使用 matchesSelector js 检查 event target parentElement https stackoverflow com questions 12977658 check
  • python 函数返回 javascript date.getTime()

    我正在尝试创建一个简单的 python 函数 它将返回与 javascript 相同的值new Date getTime 方法 如所写here http www w3schools com js js dates asp javascrip
  • gatsbyjs、reactjs - 为什么组件渲染两次而图像没有出现?

    我是新来的gatsbyjs并使用 v2 我有 3 个组件 加载器 标题和布局 layout js import React from react import Helmet from react helmet import StaticQu
  • Chrome 中的 addEventListener

    我正在关注 Lynda com 上有关新 DOM 事件模型的教程 这是我正在使用的代码 function addEventHandler oNode sEvt fFunc bCapture if typeof window event un

随机推荐

  • Error:Unable to start the daemon process.解决

    导入一个项目出现了以下错误 Error Unable to start the daemonprocess This problem might be caused by incorrect configuration of the dae
  • 显示等待和隐式等待

    学习显示等待和隐式等待使用 参考博客原址 https blog csdn net sinat 41774836 article details 88965281 文章目录 强制等待 sleep 隐式等待 implicitly wait 显示
  • 【Linux命令详解

    文章目录 简介 一 参数列表 二 使用介绍 1 修改用户权限 2 修改用户组权限 3 修改其他用户权限 4 同时修改多个权限 5 使用数字模式设置权限 6 递归修改目录权限 总结 简介 在Ubuntu系统中 chmod命令是一个强大的工具
  • 疯壳Android嵌入式Linux平板开发教程3-9G-sensor

    详情地址 https fengke club GeekMart views offline android 购买链接 https fengke club GeekMart su fHnaDyD1o jsp 视频地址 https fengke
  • c字符串分割成数组_leetcode第31双周赛第三题leetcode1525. 字符串的好分割数目

    leetcode1525 字符串的好分割数目 给你一个字符串 s 一个分割被称为 好分割 当它满足 将 s 分割成 2 个字符串 p 和 q 它们连接起来等于 s 且 p 和 q 中不同字符的数目相同 请你返回 s 中好分割的数目 示例 1
  • HCIP考试考哪三门你知道么?

    HCIP考试考哪三门 HCIP是华为认证中资深级别的认证 与hcia相比 它可能需要考多门考试 只有都通过了 才能获得HCIP认证 那么HCIP考试要考哪三门呢 其实 不同的方向需要通过的考试门数各不相同 有的只要通过一门 有的则是两门 最
  • kettle转换中文数据出现乱码

    在使用kettle转换数据时 有时会出现中文乱码问题 下面介绍解决办法 首先先保证你自己创建或连接的数据库是utf 8编码 1 设置DB连接 打开kettle中连接的数据库 在高级中输入set names utf8 2 再到选项中命名参数
  • Flink服务器无响应,apache-flink

    在这种情况下 我们有3个kafka主题 每个主题有50个分区 它们具有不同的消息 而所有这些消息都具有 用户名 字段 topic 1 gt Message01 String username about 50 000 messages pe
  • 分析Java线程池执行原理

    Java并发编程源码分析系列 分析Java线程池的创建 上一篇已经对线程池的创建进行了分析 了解线程池既有预设的模板 也提供多种参数支撑灵活的定制 本文将会围绕线程池的生命周期 分析线程池执行任务的过程 线程池状态 首先认识两个贯穿线程池代
  • Vue2.0 Vue脚手架 插件

    Vue当中有一个特别强大但写起来特别简单的一个东西 名字叫 插件 有什么作用 可以帮我们去增强一下Vue 先配置好项目 自己写的话 main js 项目执行npm run serve后第一个进入的 import Vue from vue i
  • maven报错‘has elapsed or updates are forced“

    使用 U强制更新参数运行maven命令
  • 少儿机器人编程有什么用

    少儿机器人编程有什么用 小孩的学习一直以来都是家长们非常关心和重视的一件事情 很多的家长在培养孩子的学习方面也可以说是相当的耐心的 会给孩子选择一些能更有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对于
  • 解决Enter passphrase for key

    两种解决方案 提示 Permissions 0644 for ssh id rsa pub are too open 解决方法 使用chmod 0600 ssh id rsa pub更改将公钥权限改成 600 提示 Enter passph
  • Java中的静态变量&静态方法

    静态变量 静态方法 静态变量又叫做类变量 静态方法又被称为类方法 均被static修饰 未被static修饰的成员变量和方法分别被称为实例变量和实例方法 1 静态方法中不需要它所属类的任何实例就可以访问 所以在静态方法中不可以使用this关
  • Swift语法学习--运算符与流程控制

    文章目录 运算符 循环 条件 预处理器指令 运算符 普通的运算符加减乘除 与或非 三元运算我觉得没必要再赘述了 就记录一下我不熟悉的 循环 条件 预处理器指令
  • SQL Server 数据库中添加文件组和数据文件

    SQL Server 现有数据库中添加文件组和数据文件 use CURRENT DB 进入当前操作数据库 go alter database CURRENT DB add filegroup FG1 向CURRENT DB 数据库添加FG1
  • idea安装插件plugin(主要针对网络连接不上的情况)

    STEP1 ctrl alt s 打开settings STEP2 在输入框键入 Plugins STEP3 输入你想要的插件名称 我这边输入的是nodejs 因为最近在学 我这边是安装过的 所以这样显示 STEP4 点开中下方的前两个按钮
  • 在windows下编译glib库

    glib库是跨平台的C语言函数库 是Gtk 库和Gnome的基础 glib可以在多个平台下使用 比如Linux Unix Windows等 glib为许多标准的 常用的C语言结构提供了相应的替代物 先从官网下载下载 https downlo
  • Linux网络通信总结

    网络IO之阻塞 非阻塞 同步 异步 单播 多播 组播 广播 多路复用POLL SELECT epoll 超时 read write accept connect 超时 实现 1 用select来设置超时机制 2 使用setsockopt 函
  • React 子向父级组件通信时,state为旧的数据

    问题描述 当嵌套太深的子组件触发更新父组件时 父组件获取到的state map传入子组件 是旧的 问题场景 初始子组件仅为1个Input输入框 新增后有2个Input输入框 此时触发222输入框的修改 通知上级组件保存修改的内容时 父组件存