React-bootstrap модальный, как обрабатывать дочерний компонент?

Я использую модальный код на основе примера кода из документации: https://react-bootstrap.github.io/components.html#modals-live. Я хочу, чтобы дочерний компонент отображался только тогда, когда 1) данные готовы, и 2) когда модальное окно открыто. Кроме того, дочерний компонент должен знать, насколько широка область, с которой он должен работать (потому что внутри он рисует d3.js svg).

Я также, кстати, использую fixed-data-table, поэтому данные (concept) помещаются в состояние, а Модель открывается при щелчке по строке:

onRowClick={(evt, idx, obj)=>{
  let concept = filteredDataList.getObjectAt(idx);
  this.openModal();
  this.setState({concept});
}}

Согласно примеру Modal docs, Modal находится там в рендере и существует в DOM в закрытом состоянии, пока что-то его не откроет. Однако Modal.Body, похоже, не существует, пока Modal не открыт. Моя блестящая идея состоит в том, что дочерний элемент ConceptDetail может получить ClientWidth из ссылки в содержащий ее div.

let conceptDetail = '';
if (this.state.concept) {
    conceptDetail = <ConceptDetail 
                        containerRefs={this.refs}
                        concept={concept} />/
}

<Modal>
   ...
  <Modal.Body>
    <div ref="modalBody" style={{width:'100%'}}>
        {conceptDetail}
    </div>
  </Modal.Body>
  ...
</Modal>

Это будет работать, за исключением того, что ссылка не готова до тех пор, пока дочерний компонент не будет отрисован. Чтобы понять, что происходит, я сделал следующее:

componentWillUpdate(){
  if (this.refs.modalBody) {
    let { clientWidth } = this.refs.modalBody;
    alert(`will update, width: ${clientWidth}`);
  } else {
    alert('will update, no modalBody ref');
  }
}
componentDidUpdate(){
  if (this.refs.modalBody) {
    let { clientWidth } = this.refs.modalBody;
    alert(`did update, width: ${clientWidth}`);
  } else {
    alert('did update, no modalBody ref');
  }
}

Когда я щелкаю строку, я вижу предупреждение will update, no modalBody ref, за которым следует предупреждение did update, width: 868, а затем отображается дочерний компонент. Но дочерний элемент не получил ширину (или обновленную ссылку), потому что он фактически отображается до componentDidUpdate. Причина, по которой я сначала вижу предупреждение (я полагаю), заключается в том, что модальное окно анимировано и не появляется сразу при рендеринге. Когда я закрываю модальное окно, я действительно вижу на мгновение, что он, наконец, получил правильную ширину, но в этот момент он мне больше не нужен.

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


person Sigfried    schedule 19.11.2016    source источник


Ответы (1)


Хорошо, поэтому частичный ответ, который меня заставил, здесь: Показан модальный триггер для React Bootstrap

Итак, onEntered не срабатывает, пока модальное окно не будет полностью готово, так что самое время получить ширину:

<Modal ... 
    onEntered={(() => {
      let { clientWidth } = this.refs.modalBody;
      if (this.state.modalWidth !== clientWidth)
        this.setState({modalWidth:clientWidth});
    }).bind(this)}>
...
  <Modal.Body>
    <div ref="modalBody">
      {this.getConceptDetail()}
    </div>
  </Modal.Body>
...
</Modal>

Затем отдельный метод получения дочернего компонента (если готов):

getConceptDetail() {
  const {concept, modalWidth} = this.state;
  if (concept && modalWidth) {
    let conceptId = concept.records[0].rollupConceptId;
    return <ConceptDetail 
              width={modalWidth}
              concept={concept} 
              conceptId={conceptId}/>;
  }
  return <h3>no concept detail</h3>;
}

Думаю, в этом нет ничего страшного, и это работает. Если кто-то знает, как это структурировать получше, я был бы рад услышать.

ПРИЛОЖЕНИЕ: вроде работ. Дочерний компонент, которому на самом деле нужно знать ширину, находится на пару уровней ниже модального тела, поэтому ему нужно знать ширину своего прямого родителя ... grrr Как предполагается реагировать на компоненты чтобы знать их контейнерные направления ??

person Sigfried    schedule 19.11.2016