Передать реквизит для родительского компонента в реакции.js
есть ли не простой способ передать ребенка props к своему родителю, используя события, в React.Джей?
var Child = React.createClass({
render: function() {
<a onClick={this.props.onClick}>Click me</a>
}
});
var Parent = React.createClass({
onClick: function(event) {
// event.component.props ?why is this not available?
},
render: function() {
<Child onClick={this.onClick} />
}
});
Я знаю, что вы можете использовать управляемые компоненты для передачи значения ввода, но было бы неплохо передать весь комплект N' kaboodle. Иногда дочерний компонент содержит набор информации,которую вам лучше не искать.
возможно, есть способ привязать компонент к событию?
обновление – 9/1/2015
после использования React for over год, и подстегнутый ответом Себастьяна Лорбера, я пришел к выводу, что передача дочерних компонентов в качестве аргументов для функций в родителях - это не на самом деле реагировать так, и это никогда не было хорошей идеей. Я поменял ответ.
6 ответов:
Edit: см. конечные примеры для обновленных примеров ES6.
этот ответ просто обрабатывает случай прямых отношений родитель-ребенок. Когда родитель и ребенок потенциально имеют много посредников, проверьте это ответ.
другие решения не хватает точки
в то время как они все еще работают нормально, другие ответы не хватает чего-то очень важного.
есть ли не простой способ передать реквизит ребенка к его родителю с помощью событий, в React.Джей?
у родителя уже есть эта дочерняя опора!: если у ребенка есть опора, то это потому, что его родитель предоставил эту опору ребенку! Почему вы хотите, чтобы ребенок передал опору родителю, в то время как родитель, очевидно, уже имеет эту опору?
лучше реализации
ребенок: это действительно не должно быть сложнее, чем что.
var Child = React.createClass({ render: function () { return <button onClick={this.props.onClick}>{this.props.text}</button>; }, });родитель с одним ребенком: используя значение, которое он передает ребенку
var Parent = React.createClass({ getInitialState: function() { return {childText: "Click me! (parent prop)"}; }, render: function () { return ( <Child onClick={this.handleChildClick} text={this.state.childText}/> ); }, handleChildClick: function(event) { // You can access the prop you pass to the children // because you already have it! // Here you have it in state but it could also be // in props, coming from another parent. alert("The Child button text is: " + this.state.childText); // You can also access the target of the click here // if you want to do some magic stuff alert("The Child HTML is: " + event.target.outerHTML); } });родитель со списком детей: у вас все еще есть все, что вам нужно на родителя и не нужно, чтобы сделать ребенка более сложным.
var Parent = React.createClass({ getInitialState: function() { return {childrenData: [ {childText: "Click me 1!", childNumber: 1}, {childText: "Click me 2!", childNumber: 2} ]}; }, render: function () { var children = this.state.childrenData.map(function(childData,childIndex) { return <Child onClick={this.handleChildClick.bind(null,childData)} text={childData.childText}/>; }.bind(this)); return <div>{children}</div>; }, handleChildClick: function(childData,event) { alert("The Child button data is: " + childData.childText + " - " + childData.childNumber); alert("The Child HTML is: " + event.target.outerHTML); } });также можно использовать
this.handleChildClick.bind(null,childIndex)и затем использоватьthis.state.childrenData[childIndex]обратите внимание, мы являются обязательными с
nullконтекст, потому что в противном случае React выдает предупреждение, связанное с его autobinding
Update (9/1/15): OP сделал этот вопрос немного движущейся целью. Он был обновлен снова. Итак, я чувствую ответственность за обновление своего ответа.
во-первых, ответ на ваш пример:
Да, это возможно.
вы можете решить эту проблему, обновив ребенка
onClickнаthis.props.onClick.bind(null, this):var Child = React.createClass({ render: function () { return <a onClick={this.props.onClick.bind(null, this)}>Click me</a>; } });обработчик событий в вашем Родителе может получить доступ к компоненту и событию, например Итак:
onClick: function (component, event) { // console.log(component, event); },
но сам вопрос вводит в заблуждение
родитель уже знает .
это не ясно в приведенном примере, потому что никакие реквизиты фактически не предоставляются. Этот пример кода может лучше поддерживать задаваемый вопрос:
var Child = React.createClass({ render: function () { return <a onClick={this.props.onClick}> {this.props.text} </a>; } }); var Parent = React.createClass({ getInitialState: function () { return { text: "Click here" }; }, onClick: function (event) { // event.component.props ?why is this not available? }, render: function() { return <Child onClick={this.onClick} text={this.state.text} />; } });в этом примере становится гораздо яснее, что вы уже знаете что такое реквизит ребенка.
если это действительно об использовании реквизита ребенка...
если это действительно об использовании реквизита ребенка, вы можете избежать любого подключения с ребенком в целом.
JSX имеет распространение атрибутами API я часто использую на таких компонентах, как Child. Это занимает все
propsи применяет их к компоненту. Ребенок будет выглядеть это:var Child = React.createClass({ render: function () { return <a {...this.props}> {this.props.text} </a>; } });позволяет использовать значения непосредственно в родительской:
var Parent = React.createClass({ getInitialState: function () { return { text: "Click here" }; }, onClick: function (text) { alert(text); }, render: function() { return <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} />; } });
и нет никакой дополнительной конфигурации, необходимой при подключении дополнительных дочерних компонентовvar Parent = React.createClass({ getInitialState: function () { return { text: "Click here", text2: "No, Click here", }; }, onClick: function (text) { alert(text); }, render: function() { return <div> <Child onClick={this.onClick.bind(null, this.state.text)} text={this.state.text} /> <Child onClick={this.onClick.bind(null, this.state.text2)} text={this.state.text2} /> </div>; } });но я подозреваю, что это не ваше дело использовать. Так что давайте копать дальше...
надежная практический пример
общий характер представленного примера трудно говорить. Я создал компонент, который демонстрирует практическое использование для вопроса выше, реализованного в очень Reacty путь:
DTServiceCalculator пример работающего
DTServiceCalculator РЕПОэтот компонент представляет собой простой калькулятор услуг. Вы предоставляете ему список услуг (с названиями и ценами) и он рассчитает общую сумму выбранных цен.
дети в блаженном неведении
ServiceItemявляется дочерним компонентом в этом примере. У него не так много мнений о внешнем мире. Это требуется несколько реквизита, одним из которых является функция, вызываемая при нажатии.
<div onClick={this.props.handleClick.bind(this.props.index)} />он ничего не делает, кроме как вызвать предоставленный
handleClickобратного вызова сindex[источник].родители детей
DTServicesCalculatorродительский компонент-это пример. Это тоже ребенок. Давайте посмотрим.
DTServiceCalculatorсоздает список дочерних компонентов (ServiceItems) и предоставляет им реквизит [источник]. Это родительский компонентServiceItemно это дочерний компонент компонента, передающего ему список. Он не владеет данными. Так что он снова делегирует обработку компонент к его родительскому компоненту источник
<ServiceItem chosen={chosen} index={i} key={id} price={price} name={name} onSelect={this.props.handleServiceItem} />
handleServiceItemзахватывает индекс, переданный от ребенка, и предоставляет его своему родителю [источник]handleServiceClick (index) { this.props.onSelect(index); }владельцы знают все
понятие "собственность" является важным в React. Я рекомендую прочитать больше об этом здесь.
в Примере, который я показал, я продолжаю делегировать обработку события вверх по дереву компонентов, пока мы не доберемся до компонента, которому принадлежит состояние.
когда мы, наконец, доберемся туда, мы обрабатываем выбор/отмену выбора состояния так [источник]:
handleSelect (index) { let services = […this.state.services]; services[index].chosen = (services[index].chosen) ? false : true; this.setState({ services: services }); }
вывод
старайтесь держать ваши внешние компоненты как можно более непрозрачными. Старайтесь, чтобы у них было очень мало предпочтений о том, как родительский компонент может выбрать для их реализации.
держите в курсе кто владеет данными, которыми вы манипулируете. В большинстве случаев вам нужно будет делегировать обработку событий вверх по дереву компоненту, который принадлежит этого государства.
В Сторону: The Flux pattern это хороший способ уменьшить этот тип необходимого подключения в приложениях.
кажется, есть простой ответ. Рассмотрим это:
var Child = React.createClass({ render: function() { <a onClick={this.props.onClick.bind(null, this)}>Click me</a> } }); var Parent = React.createClass({ onClick: function(component, event) { component.props // #=> {Object...} }, render: function() { <Child onClick={this.onClick} /> } });клавиша вызова
bind(null, this)наthis.props.onClickсобытие, переданное от родителя. Теперь функция onClick принимает аргументыcomponentиevent. Я думаю, что это лучший из всех миров.обновление: 9/1/2015
это была плохая идея: позволить дочерним деталям реализации просочиться к родителю никогда не было хорошим путем. См. ответ Себастьяна Лорбера.
вопрос в том, как передать аргумент от дочернего к родительскому компоненту. Этот пример прост в использовании и протестирован:
//Child component class Child extends React.Component { render() { var handleToUpdate = this.props.handleToUpdate; return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div> ) } } //Parent component class Parent extends React.Component { constructor(props) { super(props); var handleToUpdate = this.handleToUpdate.bind(this); } handleToUpdate(someArg){ alert('We pass argument from Child to Parent: \n' + someArg); } render() { var handleToUpdate = this.handleToUpdate; return (<div> <Child handleToUpdate = {handleToUpdate.bind(this)} /></div>) } } if(document.querySelector("#demo")){ ReactDOM.render( <Parent />, document.querySelector("#demo") ); }
в основном вы используете реквизит для отправки информации и от ребенка и родителя.
добавляя ко всем замечательным ответам, позвольте мне привести простой пример, который объясняет передачу значений от дочернего к родительскому компоненту в React
приложение.js
class App extends React.Component { constructor(){ super(); this.handleFilterUpdate = this.handleFilterUpdate.bind(this); this.state={name:'igi'} } handleFilterUpdate(filterValue) { this.setState({ name: filterValue }); } render() { return ( <div> <Header change={this.handleFilterUpdate} name={this.state.name} /> <p>{this.state.name}</p> </div> ); } }заголовок.js
class Header extends React.Component { constructor(){ super(); this.state={ names: 'jessy' } } Change(event) { // this.props.change(this.state.names); this.props.change('jessy'); } render() { return ( <button onClick={this.Change.bind(this)}>click</button> ); } }Главная.js
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App.jsx'; ReactDOM.render(<App />, document.getElementById('app'));вот и все , теперь вы можете передавать значения из своего клиента сервер.
взгляните на функцию изменения в заголовке.js
Change(event) { // this.props.change(this.state.names); this.props.change('jessy'); }это, как вы нажимаете значения в реквизит от клиента к серверу
вот простая реализация 3 шага ES6 с использованием привязки функции в Родительском конструкторе. Это первый способ, который рекомендует официальный учебник react (здесь также не рассматривается синтаксис полей общедоступных классов). Вы можете найти всю эту информацию здесь https://reactjs.org/docs/handling-events.html
привязка родительских функций, чтобы дети могли их вызывать (и передавать данные до родителя! : D)
- убедитесь, что в Родительском конструктор вы связываете функцию, созданную в Родительском
- передайте связанную функцию ребенку как опору (без лямбды, потому что мы передаем ref в функцию)
- вызов связанной функции из дочернего события (лямбда! Мы вызываем функцию, когда событие срабатывает. Если мы этого не сделаем, функция автоматически запустится при загрузке и не будет активирована на событии.)
Родительская Функция
handleFilterApply(filterVals){}родитель Конструктор
this.handleFilterApply = this.handleFilterApply.bind(this);опора передана ребенку
onApplyClick = {this.handleFilterApply}Вызов Дочернего События
onClick = {() => {props.onApplyClick(filterVals)}
Comments