React Modal всегда отключает и монтирует дочерние элементы, поэтому обратные вызовы ref имеют странное поведение. Почему это не просто возродить детей?

У меня есть модал реакции, который отображает детей:

// base_modal.js  
import React, { Component } from 'react';
import Modal from 'react-modal';

export default class BaseModal extends Component {
  componentDidMount() {
    console.log("BaseModal mounted");
  }

  render() {
    return (
      <Modal
        isOpen={this.props.showModal}
        className="base-modal"
        overlayClassName="base-modal-overlay"
        onRequestClose={this.props.onRequestClose}
        contentLabel="base-modal"
      >
        {this.props.children}
      </Modal>
    );
  }
}

У меня есть еще один компонент, который отображает проходы BaseModal у некоторых детей:

// my_modal.js
import BaseModal from './base_modal'

export default class MyModal extends Component {
  constructor(props) {
    super(props);
    this.doSomeSetup = this.doSomeSetup.bind(this);
  }

  componentDidMount() {
    console.log("MyModal mounted");
    this.doSomeSetup();
  }

  doSomeSetup() {
    console.log(this.dateInput); // undefined
  }

  render() {
    return (
       <BaseModal
        showModal={this.props.showModal}
        onRequestClose={this.props.onClose}
       >
        <form>
          <div>
            <input
              ref={ input => { console.log("In the input ref"); this.dateInput = input; }}
              type='text'
              value={this.state.inputVal}
              onChange={this.handleChange}
            />
          </div>
        </form>
      </BaseModal>
    )
  }
}

У меня есть компонент, который отображает MyModal:

// my_view.js
import MyModal from './my_modal'

export default class MyView extends Component {
  constructor(props) {
    super(props)
    this.state = {
      showModal: false
    }
    this.showModal = this.showModal.bind(this);
    this.hideModal = this.hideModal.bind(this);
  }

  showModal() {
    this.setState({
      showModal: true
    });
  }

  hideModal() {
    this.setState({
      showModal: false
    });
  }

  render() {
    return (
      <div>
        <Button onClick={this.showModal} />
        <MyModal 
          showModal={false}
          onClose={this.hideModal}
        />
      </div>
    )
  }
}

Проблема в том, что в MyModal this.dateInput не определяется при монтировании компонента. Всякий раз, когда я рендерил MyView, он рендерил MyModal, но MyModal рендерил BaseModal, который рендерил своих детей, только когда для свойства prop "isOpen" установлено значение true.

Когда я выполняю рендеринг MyView, я вижу журналы консоли "BaseModal mount", "MyModal mount", а затем "undefined" для console.log в методе doSomeSetup (т. Е. Обратный вызов ref не был выполнен). Когда я затем нажимаю на кнопку в MyView, чтобы открыть модальное окно, я вижу console.log "В ссылке ref". Таким образом, настройка, которую я хочу выполнить с вводом в MyModal, не происходит, потому что фактическая ссылка на ввод формы выполняется только тогда, когда в React Modal для prop isOpen установлено значение true.

Другая настройка заключается в внесении следующих изменений:

// my_modal.js

componentDidMount() {
  console.log("MyModal mounted");
}

doSomeSetup(input) {
  console.log(input);
}


(...) ref={ input => { console.log("In the input ref"); this.doSomeSetup(input); }}

Однако сейчас наблюдается следующее поведение. Когда я отображаю MyView, я вижу "BaseModal подключен", "MyModal подключен". Когда я нажимаю на кнопку, чтобы открыть модальное окно, я вижу "In input ref", и фактический элемент input получает console.logged.

Вот странная вещь (хотя, когда я пишу это, я начинаю видеть ответ на свои собственные сомнения): скажем, я добавляю кнопку в метод рендеринга MyModal, который просто меняет состояние inputVal, заставляя повторно вызывать:

  changeState() {
    this.setState({
      inputVal: this.state.inputVal + 1
    });
  }

  render() {
    return (
       <BaseModal
        showModal={this.props.showModal}
        onRequestClose={this.props.onClose}
       >
        <button onClick={this.changeState}
        <form>
          <div>
            <input
              ref={ input => { console.log("In the input ref"); this.doSomeSetup(input); }}
              type='text'
              value={this.state.inputVal}
              onChange={this.handleChange}
            />
          </div>
        </form>
      </BaseModal>
    )
  }

Теперь, когда я нажимаю на кнопку, происходит следующее: "На входе ref", затем выполняется console.log из doSomeSetup и выдает "null", затем я получаю еще один "На входе ref", а затем console.log от doSomeSetup создает фактический элемент ввода. Так что на самом деле кажется, что дочерние элементы, которые передаются в BaseModal (мои Button и Form), сначала размонтируются, а затем снова монтируются (я думаю, это потому, что обратные вызовы ref вызываются с нулевым аргументом, когда узел будет размонтирован). Что странно.

Итак, теперь я предполагаю, что мой вопрос: имеет ли смысл приведенное выше, и нормально ли, что родительский компонент каждый раз монтирует и монтирует свои дочерние элементы? Это даже правильный способ описать, что происходит?

Чтобы быть более точным, функциональность, которую я хочу, это добавить обработчик событий для ввода в doSomeSetup. Но кажется, что в любое время входные данные должны были измениться, поскольку они содержатся в дочернем элементе BaseModal, который является опорой для BaseModal, последний каким-то образом решает размонтировать и смонтировать дочерние элементы. Почему это не просто возродить детей? Есть лучший способ сделать это?

0 ответов

Другие вопросы по тегам