Передать реквизит для родительского компонента в реакции.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 год, и подстегнутый ответом Себастьяна Лорбера, я пришел к выводу, что передача дочерних компонентов в качестве аргументов для функций в родителях - это не на самом деле реагировать так, и это никогда не было хорошей идеей. Я поменял ответ.

543   6  

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);
  }
});

JsFiddle

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

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);
  }
});

JsFiddle

также можно использовать 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);
  },

снимок JSBin


но сам вопрос вводит в заблуждение

родитель уже знает .

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

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} />;
  }
});

в этом примере становится гораздо яснее, что вы уже знаете что такое реквизит ребенка.

снимок JSBin


если это действительно об использовании реквизита ребенка...

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

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} />;
  }
});

снимок JSBin


и нет никакой дополнительной конфигурации, необходимой при подключении дополнительных дочерних компонентов

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>;
  }
});

снимок JSBin

но я подозреваю, что это не ваше дело использовать. Так что давайте копать дальше...


надежная практический пример

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

DTServiceCalculator пример работающего
DTServiceCalculator РЕПО

этот компонент представляет собой простой калькулятор услуг. Вы предоставляете ему список услуг (с названиями и ценами) и он рассчитает общую сумму выбранных цен.

дети в блаженном неведении

ServiceItem является дочерним компонентом в этом примере. У него не так много мнений о внешнем мире. Это требуется несколько реквизита, одним из которых является функция, вызываемая при нажатии.

<div onClick={this.props.handleClick.bind(this.props.index)} />

он ничего не делает, кроме как вызвать предоставленный handleClick обратного вызова с index[источник].

родители детей

DTServicesCalculator родительский компонент-это пример. Это тоже ребенок. Давайте посмотрим.

DTServiceCalculator создает список дочерних компонентов (ServiceItem s) и предоставляет им реквизит [источник]. Это родительский компонент 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")
    );
}

посмотрите на JSFIDDLE

в основном вы используете реквизит для отправки информации и от ребенка и родителя.

добавляя ко всем замечательным ответам, позвольте мне привести простой пример, который объясняет передачу значений от дочернего к родительскому компоненту в 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)

  1. убедитесь, что в Родительском конструктор вы связываете функцию, созданную в Родительском
  2. передайте связанную функцию ребенку как опору (без лямбды, потому что мы передаем ref в функцию)
  3. вызов связанной функции из дочернего события (лямбда! Мы вызываем функцию, когда событие срабатывает. Если мы этого не сделаем, функция автоматически запустится при загрузке и не будет активирована на событии.)

Родительская Функция

handleFilterApply(filterVals){} 

родитель Конструктор

this.handleFilterApply = this.handleFilterApply.bind(this);

опора передана ребенку

onApplyClick = {this.handleFilterApply}

Вызов Дочернего События

onClick = {() => {props.onApplyClick(filterVals)}

Comments

    Ничего не найдено.