如何使用React Function组件获取组件的位置

如何解决如何使用React Function组件获取组件的位置

我正在尝试做这样的事情:

enter image description here

当我单击左侧的卡,然后ctrl +单击右侧的卡时..将画一条线。再次按住Ctrl键并单击右侧的卡片,该行将被删除。我将使用svg路径绘制线条,但必须在容器组件中获取卡片的位置。

我正在尝试使用ref使用React Function组件执行此操作,但我不太了解。我知道函数组件没有“实例”,因此ref不能像类中那样正常工作。

请回答以下问题:

  • 是否可以仅使用功能组件来做到这一点?
  • 哪些组件需要包装在React.forwardRef()中?
  • 我读到我可以将一个函数从Container传递给ref属性中的子代,并且子代可以在单击时调用该函数。那是真的,那会是什么样?
  • 奖金:我已经多次阅读React Refs and the DOM文档,但对我而言它不会单击。谁能在我的背景下解释它?

感谢您的任何帮助,并在此先感谢!

编辑

这是我到目前为止所拥有的:

ContainerComponent

import React,{ useState,useRef } from 'react';

import { Container,Row,Col,Card,Button } from 'reactstrap';
import SectionContainer from './SectionContainer';

const ContainerComponent = (props) => 
{
    const [keyCards,setKeyCards] = useState([
        { id: 1,name: 'key one',description: "this is a key card for one" },{ id: 2,name: 'key two',description: "this is a key card for two" }
    ])

    const [valueCards,setValueCards] = useState([
        { id: 1,name: 'value one',description: "this is a value card" },name: 'value two',{ id: 3,name: 'value three',description: "this is a value card" }
    ])

    const [connections,setConnections] = useState([
        // I need something like this for all connections that need a line
        {
            keyID: 1,keyPos: { x: 100,y: 200 },attachedValues: [
                { valueID: 1,valPos: { x: 200,y: 200 } },{ valueID: 2,y: 300 } }
            ]
        }
    ])

    const cardRef = useRef()

    const getPositions = () =>
    {
        console.log(cardRef.current)
        // if I can get positions and if they are selected
        // then I can set the state and generate svg paths
    }

    return (
        <>
            <Row >
                <Col className="display-section" md='6'>
                    <SectionContainer
                        title="Rules for Life"
                        items={keyCards}
                        cardRef={cardRef}
                        onClickHandler={getPositions}
                    />
                </Col>

                <Col className="display-section" md='6'>
                    <SectionContainer
                        title="Entitlements for Days"
                        items={valueCards}
                        cardRef={cardRef}
                        onClickHandler={getPositions}
                    />
                </Col>
            </Row>
            {/* <DrawLines connections={connections} /> */}
        </>
    )
}

export default ContainerComponent 

SectionContainer

import React from 'react';

import { Row,Input,InputGroup,InputGroupAddon,InputGroupText } from 'reactstrap';

import CardContainer from './CardContainer'

const SectionContainer = ({ title,items,cardRef,onClickHandler }) => 
{
    return (
        <>
            <h6>{title}</h6>
            <Row >
                <InputGroup>
                    <InputGroupAddon addonType="prepend" >
                        <InputGroupText>filter:</InputGroupText>
                    </InputGroupAddon>
                    <Input />
                </InputGroup>
            </Row>
            <CardContainer
                items={items}
                cardRef={cardRef}
                onClickHandler={onClickHandler}
            />
        </>
    )
}

export default SectionContainer

卡片容器

import React from 'react'
import { Container,Row } from 'reactstrap'
import CardComponent from './CardComponent'

const CardContainer = ({ items,onClickHandler }) => 
{
    const getItems = (items) =>
    {
        return items.map(item =>
        {
            return <Row key={item.id}>
                <CardComponent
                    item={item}
                    cardRef={cardRef}
                    onClickHandler={onClickHandler}
                />
            </Row>
        })
    }
    return (
        <Container fluid className="node-container">
            {getItems(items)}
        </Container>
    )
}

export default CardContainer

卡组件

import React,{ useState } from 'react';

import { Card,CardHeader,CardTitle,CardBody,CardText } from 'reactstrap';

const CardComponent = React.forwardRef(({ item,onClickHandler },ref) => 
{
    return (
        <Card ref={cardRef} >
            <CardHeader onClick={onClickHandler} >
                <CardTitle>{item.name}</CardTitle>
            </CardHeader>
            <CardBody>
                <CardText>{item.description}</CardText>
            </CardBody>
        </Card>)
})

export default CardComponent

这将显示与上图类似的卡片,没问题。我只是无法使裁判工作。

即使我已经用React.ForwardRef()包裹了CardComponent,我也会遇到以下错误:

警告:不能为功能组件提供引用。尝试访问 该裁判将失败。您是要使用React.forwardRef()吗?

检查ForwardRef的渲染方法。 在Card中(在CardComponent.js:8) ...

修改

我通过将Card包裹在div中解决了forwardRef()错误。即使引导卡显示为div,您也无法引用它。

只有一个位置向上传递到ContainerComponent。仍在努力。

新CardComponent

import React,CardText } from 'reactstrap';

const CardComponent = ({ item,onClickHandler }) =>
    (
        <div ref={cardRef}>
            <Card >
                <CardHeader onClick={onClickHandler} >
                    <CardTitle>{item.name}</CardTitle>
                </CardHeader>
                <CardBody>
                    <CardText>{item.description}</CardText>
                </CardBody>
            </Card>
        </div>
    )


export default CardComponent

解决方法

使用react钩子,您基本上可以完成在功能组件的类组件中所做的任何事情。

我想您可以使用getBoundingClientRect()来获得职位。

import React,{ useRef } from 'react';
//import Card from '.../...';

const App = () =>
{
    const cardRef = useRef();

    const onClickHandler = () =>
    {
        const position = cardRef.current.getBoundingClientRect();
        //This returns an object with left,top,right,bottom,x,y,width,and height.
        console.log(position)
    }

    return (
        <div>
            <Card cardRef={cardRef} onClickHandler={onClickHandler} />
        </div>
    );

}

export default App

const Card = ({ cardRef,onClickHandler }) => (
    <div ref={cardRef} onClick={onClickHandler}>
        <button > Click Me </button>
    </div>
)

,

我将在这里回答我自己的问题。因为我的问题很模糊,所以我对社区有欠。非常感谢@dlya的回答,这使我走上了正义之路:)

  • 是否可以仅使用功能组件来做到这一点?

是的。我能够在没有一流组件的情况下端到端地完成任务。

  • 哪些组件需要包装在React.forwardRef()中?

没有。我最终根本不必使用React.forwardRef()。实际上...我也没有使用useRef()或useEffect()。我只是将一个函数传递给了孩子,然后将该函数添加到了ref中:

<Card innerRef={updateCardLocations} id={`${type}-${item.id}`}>

请注意,我必须使用innerRef而不是ref,因为我确实需要获取reactstrap ref而不是将Card包裹在div中。

然后我像这样收集我在父母中的所有卡位:

    let connections = {}

    const updateCardLocations = (card) =>
    {
        if (card)
        {
            const id = card.id.substr(card.id.indexOf("-") + 1)
            const pos = card.getBoundingClientRect()

            connections[id] = {
                ...connections[id],connectionPoint: [pos.right,pos.top + (pos.height / 2)]
            }

            console.log(connections)
        }
    }

  • 我读到我可以将一个函数从Container传递给子容器中的子代 ref属性,并且子级可以在单击时调用该函数。那是真的,那会是什么样?

我刚刚展示了上一个项目符号的外观。父级具有称为updateCardLocations的功能,该功能作为道具传递给子级。将updateCardLocations函数prop传递给Child中的ref。就我而言,innerRef。

  • 奖金:我已经读过 React Refs和DOM文档几次,它只是 不会点击我的。谁能在我的背景下解释它?

我在文档中缺少的是,您只是在父级中创建一个占位符,并将其作为道具传递给子级组件。然后,在呈现子组件时,它将使用其dom信息更新该占位符。在获得成功的实践经验之前,我不会完全掌握所有内容……但是在我的辩护中,整个forwardRef确实使我感到困惑,因为我无法确定我正在向哪个方向转发裁判,那时我仍然以为我也使用useRef()在父级中创建了ref。希望这可以帮助像我一样容易困惑的人:)

这里是working sample on CodeSandbox。我还包括一个添加卡片的onClickHandler,您可以在控制台中看到位置更新。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res