当前位置:   article > 正文

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

react 获取循环组件示例

背景

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

思考

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

const ref = useRef(null);

<div ref={ref}>...</div>
  • 1
  • 2
  • 3

这里主要说的是怎么一次性获取多个子组件实例,用到这个场景的也有,可能也不大多,我刚开始也在网上找了一大堆,基本没有相关的答案,这整的我 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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

成功运行后的界面如下:

在这里插入图片描述

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

知识点总结

uesRef() 作对象处理

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

最后

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/411852
推荐阅读
相关标签
  

闽ICP备14008679号