如何解决如何使用React Function组件获取组件的位置
我正在尝试做这样的事情:
当我单击左侧的卡,然后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 举报,一经查实,本站将立刻删除。