How do you reliably measure React components for computed position of popovers and callouts?

荒凉一梦 提交于 2020-01-05 05:42:05

问题


I'm using react and react-bootstrap. I want to know whether there's a better, cleaner, more idiomatic approach than what I've come up with.

The Problem

I want to position a popover callout that points to a button on my page that provides a hint for where the user should start their workflow. The user can subsequently dismiss this popover. It took me a long time to figure out this hack-y approach to measure the elements' dimensions and positions to properly position the callout:

The target of the callout:

<Button 
  bsClass="button" 
  className="button-blue" 
  id="connectParentsButton"
  onClick={( event ) => { this.handleOpenInviteParents( event );}}
  ref={( input ) => { this.connectParentsButtonRef = input; }}
>
  + Connect Parents
</Button> 

The idea is to use ref to store the target as a property of the parent React component, and then access it from the sibling callout component to perform the measurements.

The callout component:

<RightBottomHintBox 
  isShow={this.state.isShowConnectParentsHint && !this.state.isDismissHideConnectParentsHint} 
  target={this.connectParentsButtonRef} 
  id="connectParentsHint" 
  onHide={this.handleHideConnectParentsHint}
/>

In my RightBottomHintBox component, I have to

  • use document.getElementById() to get dimenions and positions
  • use guards to avoid trying to access nodes that don't exist yet
  • store dimensions and coordinates in class properties rather than component state

And I have to do this in the the callout's render() to ensure that my callout component gets mounted even if it's not displayed, so that the DOM node exists and can be correctly measured.

let myStyle = this.props.isShow ? {} : { visibility: 'hidden' };

Failed approaches

  • computing dimensions when the callout's componentDidMount() fires. The DOM nodes of either the callout or the target are often not yet there

  • computing dimensions when the parent component's componentDidMount() fires. The same problem exists, you can't be sure that the DOM nodes exist at this point.

The above two approaches led me to this thread: When exactly is `componentDidMount` fired?

One post suggests that to be sure that all DOM nodes are ready, you'd have to go up to the top component. I don't like this approach because it would break encapsulation and separation of concerns.

Another thread, How can I respond to the width of an auto-sized DOM element in React?, suggests using the react-measure library to do measurements, which might work, but for my particular case, I wanted to avoid having another library to manage because this app is small.

Background context

I'm creating a page that allows the user to input a list of students' parents' email addresses. The initial page lists students and parents' email addresses that have already been input. However, the first time the user comes to this page, there may be a list of students, with no parent email addresses. I want to provide a hint to the user that they should click on 'Connect Parents' button to open up a wizard to guide the user in data input.


回答1:


I have another failed attempt here that may spur someone to the correct solution.

export function getSize(cpt) {
    var elem = document.getElementById("ruler");    
    const html = ReactDOMServer.renderToStaticMarkup(cpt);
    elem.innerHTML = html;
    return [elem.scrollWidth, elem.scrollHeight];
}

var Foo = React.createClass({
  componentDidMount() {
    const sz = this.elem.getBoundingClientRect();
    ReactDOM.render(<span>{ [sz.width,sz.height].join("x") }</span>,
                    document.getElementById('actual'));
  },
  render() {
    return <div ref={e => { this.elem = e; }} className="content">
             <p> Bar!! BAZ </p> <p> another line </p> </div>;
  }
})

Setting up getSize to render into any div (onscreen or off) gives about 76x84, while the actual size reported by componentDidMount (and confirmed by dev tools) is 188x52.



来源:https://stackoverflow.com/questions/40939133/how-do-you-reliably-measure-react-components-for-computed-position-of-popovers-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!