2015-04-09 4 views
11

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

Скажем, у вас есть ссылка на родителя, который показывает модальное

В модальной, у вас есть «X», который закрывает его.

Я знаю, что может изменить состояние модального от родителя с помощью реквизита

// In the parent 
<Modal display={this.state.showModal} /> 

// In the modal 
<div className={this.props.display ? "show" : "hide"}> 
    <a className="close">&times;</a> 
    ... 
</div> 

И я знаю, как закрыть модальный, но не оба. Не знаете, как сохранить состояние, которое является общим и контролируемым как родительским, так и дочерним модальным.

UPDATE

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

var ParentThing = React.createClass({ 
    ... 
    render (
    <Modal /> // How can I call this.open in the modal from here? 
) 
}); 

var Modal = React.createClass({ 
    setInitialState: function() { 
    return { 
     display: false 
    } 
    }, 
    close: function() { 
    this.setState({ display: false }); 
    }, 
    open: function() { 
    this.setState({ display: true }); 
    }, 
    render: function() { 
    return (
     <div className={this.state.display ? "show" : "hide"}> 
     <a className="close" onClick={this.close}>&times;</a> 
     </div> 
    ) 
    } 
}); 

Я видел этот метод, но, похоже, это немного больше, чем мне нужно здесь. Reactjs: how to modify child state or props from parent?

ответ

15

Есть два способа обработки такого рода вещи в React:

  1. сделать ребенка «под контролем», так же, как форма ввода с value и onChange, где владелец ввода управляет входом.
  2. Сделайте ребенка «неконтролируемым», как и вход формы без value.

Второй вариант кажется быстрее вперед, но так же, как управление коллекцией форм входов в React, преимущество использования полностью контролируемых компонентов становится очевидным, поскольку сложность сборки и необходимость в полной мере описать свой пользовательский интерфейс на любой время и время. (См this excellent answer от FakeRainBrigand, если вам интересно, почему именно контролируемые компоненты лучше, чем неконтролируемый в большинстве случаев.)

Однако, как форма входа, нет никаких причин, компонент не может быть либо контролируется или неконтролируемой. Если пользователь передает свойство display и onClose, например Austin Greco's answer, у вас есть управляемый модальный, и родитель полностью решает, когда показывать или скрывать модальный.

Если пользователь не, вы можете пропустить, используя свойства и вместо того, чтобы делегировать внутреннее состояние управляемых государственными методами на модальный компонент:

var ParentThing = React.createClass({ 
    ... 
    render: function() { 
    return <Modal ref="modal" />; 
    }, 

    handleSomeClick: function() { 
    this.refs.modal.open(); 
    } 
}); 

var Modal = React.createClass({ 
    setInitialState: function() { 
    return { 
     display: false 
    } 
    }, 
    close: function() { 
    this.setState({ display: false }); 
    }, 
    open: function() { 
    this.setState({ display: true }); 
    }, 
    render: function() { 
    return (
     <div className={this.state.display ? "show" : "hide"}> 
     <a className="close" onClick={this.close}>&times;</a> 
     </div> 
    ) 
    } 
}); 

Если вам нравится идея контролируемый Модальный компонент, но не хотите делать все печатные команды, вы даже можете зайти так далеко, чтобы реализовать что-то вроде свойства valueLink для Modal, чтобы упростить этот шаблон.

var ParentThing = React.createClass({ 
    ... 
    mixins: [React.addons.LinkedStateMixin], 

    getInitialState: function() { 
    return { showModal: false }; 
    }, 

    render: function() { 
    return <Modal displayLink={this.linkState("showModal")} />; 
    }, 

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

var Modal = React.createClass({ 
    close: function() { 
    this.props.displayLink.requestChange(false); 
    }, 

    render: function() { 
    return (
     <div className={this.props.displayLink.value? "show" : "hide"}> 
     <a className="close" onClick={this.close}>&times;</a> 
     </div> 
    ) 
    } 
}); 

(см my blog post on creating custom components that work with linkState/valueLink for more info.)

Итак, теперь вы получаете выгоду от использования полностью родительское управлением Modal, но вы удалили часть шаблонного вокруг создания функции, которая устанавливает значение до false и передать его модальному.

+0

Этот ответ - задира. –

6

Вы можете передать функцию обратного вызова в качестве опоры для ребенка компонента:

// In the parent 
<Modal display={this.state.showModal} onClose={this.closeModal} /> 

// In the modal 
<div className={this.props.display ? "show" : "hide"}> 
    <a className="close" onClick={this.props.onClose}>&times;</a> 
    ... 
</div> 

Затем при нажатии на кнопку закрытия на ребенка, он будет вызывать функцию родительского

+1

Хмм, я не знал, что вы можете это сделать. Это может сделать трюк, но это все равно беспокоит меня, что логика вокруг открытия и закрытия модальности не * в * модальной переменной jsx. Похоже, я должен быть в состоянии нести эту логику со мной, где бы я ни положил модальность. –

+0

Что делать, если вы задаете состояние родителя для '{modal: {display: false}}' и передаете это через опору и используете метод componentWillReceiveProps (реквизит) в модуле? Это позволит вам поддерживать состояние отображения модального файла без необходимости передавать метод close из родительского компонента. – chaseadamsio

Смежные вопросы