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, последний каким-то образом решает размонтировать и смонтировать дочерние элементы. Почему это не просто возродить детей? Есть лучший способ сделать это?