Как вы можете надежно измерить компоненты React для вычисленного положения всплывающих окон и выноски?

Я использую реакцию и реакцию-бутстрап. Я хочу знать, есть ли лучший, более чистый и идиоматический подход, чем то, что я придумал.

Эта проблема

Я хочу разместить выноску всплывающего окна, которая указывает на кнопку на моей странице, которая дает подсказку о том, где пользователь должен начать свой рабочий процесс. Впоследствии пользователь может закрыть это всплывающее окно. Мне потребовалось много времени, чтобы понять этот хитрый подход к измерению размеров и положений элементов, чтобы правильно расположить выноску:

Цель выноски:

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

Идея состоит в том, чтобы использовать ref для сохранения цели как свойства родительского компонента React, а затем обращаться к ней из родственного компонента выноски для выполнения измерений.

Компонент выноски:

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

В моем RightBottomHintBox компоненте я должен

  • используйте document.getElementById(), чтобы получить размеры и позиции
  • используйте охранников, чтобы не пытаться получить доступ к еще не существующим узлам
  • хранить размеры и координаты в свойствах класса, а не в состоянии компонента

И я должен сделать это в render() выноски, чтобы гарантировать, что мой компонент выноски будет смонтирован, даже если он не отображается, чтобы узел DOM существовал и его можно было правильно измерить.

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

Неудачные подходы

  • вычисление размеров при срабатывании componentDidMount() выноски. Узлы DOM либо выноски, либо цели часто еще не существуют

  • вычисление размеров при срабатывании componentDidMount() родительского компонента. Та же проблема существует, вы не можете быть уверены, что узлы DOM существуют на этом этапе.

Два вышеуказанных подхода привели меня к этой теме: Когда именно запускается `componentDidMount`?

В одном сообщении предлагается, чтобы убедиться, что все узлы DOM готовы, вам нужно перейти к верхнему компоненту. Мне не нравится этот подход, потому что он нарушит инкапсуляцию и разделение проблем.

Другой поток, Как я могу реагировать на ширину элемента DOM с автоматическим размером в React?, предлагает использовать react-measure" для измерений, которые могут сработать, но в моем конкретном случае я не хотел бы управлять другой библиотекой, потому что это приложение маленькое.

Фоновый контекст

Я создаю страницу, которая позволяет пользователю вводить список адресов электронной почты родителей учащихся. На начальной странице перечислены уже введенные адреса электронной почты учащихся и родителей. Однако в первый раз, когда пользователь заходит на эту страницу, там может быть список студентов без родительских адресов электронной почты. Я хочу подсказать пользователю, что он должен нажать кнопку «Подключить родителей», чтобы открыть мастер, который поможет пользователю при вводе данных.


person Clinton Chau    schedule 02.12.2016    source источник


Ответы (1)


У меня есть еще одна неудачная попытка здесь, которая может подтолкнуть кого-то к правильному решению.

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>;
  }
})

Настройка getSize для рендеринга в любой div (на экране или в выключенном состоянии) дает около 76x84, в то время как фактический размер, сообщаемый компонентом componentDidMount (и подтвержденный инструментами разработки), составляет 188x52.

person David M. Rogers    schedule 18.03.2017