React 使用 useRef() 获取循环中所有子组件实例

目录

  • 背景
  • 思考
  • 实现
    • 完整代码:
    • 成功运行后的界面如下:
  • 知识点总结
    • uesRef() 作对象处理
    • useImperativeHandle() 父组件操作引入子组件的内部方法
    • 最后

背景

之前项目中使用了antd pro 中的 可编辑表格 (EditableProTable),在页面中表格要经过多层遍历后组成的新页面,所以我将之抽成了一个公用的组件,另外在遍历的最外层需要通过一个按钮统一提交表格数据,但是提交数据之前需要对每一个表格进行非空校验。

思考

遍历中引入组件这个没啥好说的,根据以往的经验来说,一般要获取某个 JSX 节点都是采用的 useRef() 这个Hook,大多写法如下:

const ref = useRef(null);

<div ref={ref}>...</div>

这里主要说的是怎么一次性获取多个子组件实例,用到这个场景的也有,可能也不大多,我刚开始也在网上找了一大堆,基本没有相关的答案,这整的我 cv大法 自然也用不了,可是项目又赶得急,总的想办法解决吧,最后我盯上了ChtGPT,通过智能答案在这里获取到了一定的参考,如下:

在这里插入图片描述
既然已经有了灵感(参考),那就依样画葫芦呗,开整。

下面是我经过项目实践后,再次做的一个案例,希望能够对有需要的朋友一些帮助,可能写的不够优雅,还请大家多多包涵。如有更好的方式,请大家多多留言扶正,多谢。

实现

完整代码:

import { Button, message } from "antd";
import { useImperativeHandle, useRef } from "react";


interface paramsType {
    id: number,
    title: string,
}

interface validateFieldsObjType {
    [key: number]: boolean;
}

// 子组件
const ChildComponentPage:React.FC = (props: any) => {

    const { id, title, onRef } = props;

    const divStyleObj = {
        width: '100%',
        height: '100px',
        background: 'red',
        marginTop: '20px',
        fontSize: '20px',
        color: '#fff'
    }


    useImperativeHandle(onRef, () => {
        return {
            func
        }
    })

    const func = ():boolean => {
        console.log(`${title}(${id})被触发了`)
        if (id ===2) return false;
        else return true;
    }


    return (
        <div style={divStyleObj}>【子组件】=={title}--{id}</div>
    )
}


// 父组件
const TestRef:React.FC = () => {

    const childRefs: any = useRef({});

    // mock源数据
    const datasource:paramsType[] = [
        { id: 1, title: '组件-天天', },
        { id: 2, title: '组件-小灰', },
        { id: 3, title: '组件-阿奇', },
        { id: 4, title: '组件-驽马', },
        { id: 5, title: '组件-小栗', },
    ]


    // 异步获取所有子组件校验状态
    const getChildRefReturnStateFn = (childRefIdsArry:any) => {
        const validateFieldsObj: validateFieldsObjType = {};
        childRefIdsArry.forEach((id: number, index: number) => {
            const childRef = childRefs.current[id];
            const childReturnState = childRef.func();
            console.log('子组件实例返回状态:', id, childReturnState)
            validateFieldsObj[id] = childReturnState;
        })

        return validateFieldsObj;
    }


    // 点击事件
    const clickThisFn = async () => {
        const childRefIdsArry:any[] = Object.keys(childRefs.current);
        const validateFieldsObj: any = await getChildRefReturnStateFn(childRefIdsArry);
        console.log('子组件检查结果:', validateFieldsObj)
        const validateFieldsLen = Object.values(validateFieldsObj).filter((type)=>!type);
        if (childRefIdsArry.length !== validateFieldsLen.length) console.log('校验不通过,请再次检查数据。')
        else console.log('校验已通过')
    };

    return (
        <>
            <div style={{ width: '100%', background: 'orange', padding: '20px' }}>
                {
                    datasource.map(({ id, title }: paramsType, index: number) => {
                        return <ChildComponentPage key={id} id={id} title={title} onRef={(_ref: React.RefObject<HTMLInputElement>) => childRefs.current[id] = _ref} />
                    })
                }
            </div>

            <Button type="primary" onClick={clickThisFn}>检验全部子组件</Button>

        </>
    )
};

export default TestRef;

成功运行后的界面如下:

在这里插入图片描述

点击左侧按钮后,通过控制台可以看到相关的运行信息。

知识点总结

uesRef() 作对象处理

useImperativeHandle() 父组件操作引入子组件的内部方法

最后

关于这个问题的解决方法,就在上面的代码里面了,如果对上面的Hook使用还不清楚的,这里就不再赘述,请自行网上查看。

如果对你有所帮助,麻烦咚咚你的黄金手指,请点赞搜藏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/91076.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

远程连接虚拟机中ubuntu报错:Network error:Connection refused

ping检测一下虚拟机 可以ping通&#xff0c;说明主机是没问题 #检查ssh是否安装&#xff1a; ps -e |grep ssh发现ssh没有安装 #安装openssh-server sudo apt-get install openssh-server#启动ssh service ssh startps -e |grep ssh检查一下防火墙 #防火墙状态查看 sudo ufw…

云原生之使用Docker部署SSCMS内容管理系统

云原生之使用Docker部署SSCMS内容管理系统 一、SSCMS介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载SSCMS镜像五、部署SSCMS内容管理系统5.1 创建SSCMS容器5.2 检查SSC…

2023.8 -java - 继承

继承就是子类继承父类的特征和行为&#xff0c;使得子类对象&#xff08;实例&#xff09;具有父类的实例域和方法&#xff0c;或子类从父类继承方法&#xff0c;使得子类具有父类相同的行为。 继承的特性 子类拥有父类非 private 的属性、方法。 子类可以拥有自己的属性和方法…

深度学习11:Transformer

目录 什么是 Transformer&#xff1f; Encoder Decoder Attention Self-Attention Context-Attention 什么是 Transformer&#xff08;微软研究院笨笨&#xff09; RNN和Transformer区别 Universal Transformer和Transformer 区别 什么是 Transformer&#xff1f; ​ …

【校招VIP】TCP/IP模型之常用协议和端口

考点介绍&#xff1a; 大厂测试校招面试里经常会出现TCP/IP模型的考察&#xff0c;TCP/IP协议是网络基础知识&#xff0c;是互联网的基石&#xff0c;不管你是做开发、运维还是信息安全的&#xff0c;TCP/IP 协议都是你绕不过去的一环&#xff0c;程序员需要像学会看书写字一样…

Typora上使用Mermaid语法展示流程图、时序图、甘特图

你已经安装Typora并打开了一个新文档后,可以按照以下详细步骤在Typora上使用Mermaid语法展示流程图、时序图、甘特图 流程图 使用graph LR声明开始,并使用箭头和连接符号定义节点之间的关系。例如,A --> B表示从节点A指向节点B的箭头连接。graph TB A[界面布局图] -->…

EasyPOI 实战总结

EasyPOI实战总结 简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法 使用EasyPOI 环境搭建 # 1.引入相关依…

TensorFlow中slim包的具体用法

TensorFlow中slim包的具体用法 1、训练脚本文件&#xff08;该文件包含数据下载打包、模型训练&#xff0c;模型评估流程&#xff09;3、模型训练1、数据集相关模块&#xff1a;2、设置网络模型模块3、数据预处理模块4、定义损失loss5、定义优化器模块 本次使用的TensorFlow版本…

Leetcode 2235.两整数相加

一、两整数相加 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num1 12, num2 5 输出&#xff1a;17 解释&#xff1a;num1 是 12&#xff0c;num2 是 5 &#xff0c;它们的和是 12 5 17 &#xff0c;因此返回 17 。示例…

【OCR识别】tess4j图片识别文字

什么是OCR? OCR &#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;是指电子设备&#xff08;例如扫描仪或数码相机&#xff09;检查纸上打印的字符&#xff0c;通过检测暗、亮的模式确定其形状&#xff0c;然后用字符识别方法将形状翻译成计算机…

ServiceManager接收APP的跨进程Binder通信流程分析

现在一起来分析Server端接收&#xff08;来自APP端&#xff09;Binder数据的整个过程&#xff0c;还是以ServiceManager这个Server为例进行分析,这是一个至下而上的分析过程。 在分析之前先思考ServiceManager是什么&#xff1f;它其实是一个独立的进程&#xff0c;由init解析i…

【人脸考勤项目】

本项目主要是基于Opencv完成的人脸识别的考勤系统 人脸检测器的5种实现方法 方法一&#xff1a;haar方法进行实现&#xff08;以下是基于notebook进行编码&#xff09; # 步骤 # 1、读取包含人脸的图片 # 2.使用haar模型识别人脸 # 3.将识别结果用矩形框画出来# 导入相关包 …

ARM开发,stm32mp157a-A7核中断实验(实现按键中断功能)

1.实验目的&#xff1a;实现KEY1/LEY2/KE3三个按键&#xff0c;中断触发打印一句话&#xff0c;并且灯的状态取反&#xff1b; key1 ----> LED3灯状态取反&#xff1b; key2 ----> LED2灯状态取反&#xff1b; key3 ----> LED1灯状态取反&#xff1b; 2.分析框图: …

ACL2023 Prompt 相关文章速通 Part 1

Accepted Papers link: ACL2023 main conference accepted papers 文章目录 Accepted PapersPrompter: Zero-shot Adaptive Prefixes for Dialogue State Tracking Domain AdaptationQuery Refinement Prompts for Closed-Book Long-Form QAPrompting Language Models for Lin…

爬虫逆向实战(二十一)-- 某某点集登录与获取数据

登录 一、数据接口分析 主页地址&#xff1a;某某点集 1、抓包 通过抓包可以发现登录接口是phonePwdLogin 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有pwd和sig两个加密参数 请求头是否加密&#xff1f; 无响应是否加密&#x…

卡尔曼滤波

第一章知识点回顾 表1变量符号对照表 1.1数学期望 数学期望表示为每次可能的结果乘上结果概率的总和。 1.1.1 数学期望的性质 假设常数为 C &#xff0c;随机变量 X 和 Y &#xff0c;则 1.2 方差&#xff08;variance&#xff09; 概率论中和统计中的方差反映单个&…

Java进阶篇--进程和线程的区别

进程和线程 进程 在一个操作系统中&#xff0c;每个独立执行的程序都可称之为一个进程&#xff0c;也就是“正在运行的程序”。目前大部分计算机上安装的都是多任务操作系统&#xff0c;即能够同时执行多个应用程序&#xff0c;最常见的有Windows、Linux、Unix等。比如在Wind…

S波形及鱼眼扭曲源码

三角波形扭曲&#xff1a; void sinwave(cv::Mat& src,cv::Mat& dst) {dst.create(src.rows, src.cols, CV_8UC3);dst.setTo(0);src.copyTo(dst);int PI 3.1415;int RANGE dst.cols/2;for (int i 0; i < dst.rows; i) {double temp (dst.cols - RANGE) / 2 (d…

Git,分布式版本控制工具

1.为常用指令配置别名&#xff08;可选&#xff09; 打开用户目录&#xff0c;创建.bashrc文件 &#xff08;touch ~/.bashrc&#xff09; 2.往其输入内容 #用于输出git提交日志 alias git-loggit log --prettyoneline --all --graph --abbrev-commit #用于输出当前目录所有文…

意外发现Cortex-M内核带的64bit时间戳,比32bit的DWT时钟周期计数器更方便,再也不用担心溢出问题了

视频&#xff1a; https://www.bilibili.com/video/BV1Bw411D7F5 意外发现Cortex-M内核带的64bit时间戳&#xff0c;比32bit的DWT时钟周期计数器更方便&#xff0c;再也不用担心溢出问题了 介绍&#xff1a; 看参数手册的Debug章节&#xff0c;System ROM Table里面带Timestam…