Like many others before me (I have read the related posts and found no answers) I am doing something wrong in this code:
import React, { Component } from 'react';
export class InfoPaneArrow extends Component<InfoPaneArrowProps> {
infoPaneRef: React.RefObject<HTMLDivElement>;
positionRef: React.RefObject<HTMLDivElement>;
constructor(props: InfoPaneArrowProps) {
super(props);
this.positionRef = React.createRef();
this.infoPaneRef = React.createRef();
}
render() {
const markerBox = this.positionRef?.current?.getBoundingClientRect();
const paneBox = this.infoPaneRef?.current?.getBoundingClientRect();
const outerClass = { /* other code using markerBox & paneBox positions */ };
const innerClass = { /* you get the idea */ };
const arrowClass = { /* ... */ };
const arrowStyle = { /* ... */ };
return (
<div
className={outerClass}
ref={this.positionRef}
>
<div
className={innerClass}
ref={this.infoPaneRef}
>
{this.props.children}
<div
className={arrowClass}
style={arrowStyle}
/>
</div>
</div>
);
}
}
I think my problem might be that I'm using the refs before the render is complete, because the infoPaneRef.current
and positionRef.current
are always null - but I need the coordinates of the div
s (and the window) to do some math and determine whether to reposition the div or not (so it stays always on screen) and which side of the div the arrow should be rendered on (after repositioning).
Any idea what I'm doing wrong here and how to correct it?
CodePudding user response:
I think your guess is correct. During the mounting (first render) ref.current is null. You need to execute your logic on next rendering cycle after the component was mounted. In order to achieve this you can put markerBox
and paneBox
inside a state, set them in componentDidMount method and make your logic dependent on these state properties.
Inside a constructor add:
this.state = {markerBox: undefined, paneBox: undefined};
Add method to the class:
componentDidMount() {
const markerBox = this.positionRef?.current?.getBoundingClientRect();
const paneBox = this.infoPaneRef?.current?.getBoundingClientRect();
this.setState({markerBox, paneBox});
}
Don't forget to remove from the render method definitions of markerBox
and paneBox
variables and use state properties via this.state.markerBox
and this.state.paneBox
.