2016-05-31 4 views
4

КОНТЕКСТПередача значений через реквизит от React Stateless потомка к родителю

Я пытаюсь передать поля ввода значений (conditionTitle) от React Stateless компоненты ребенка (AddConditionSelect) в качестве родительского компонента (AddConditionDashboard), который будет держите мое состояние.

ПРОБЛЕМА

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

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

Родитель Компонент:

import AddConditionSelect from '../containers/AddConditionSelect.js'; 

class AddConditionDashboard extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     conditionTitle: '', 
     conditionType: '' 
    }; 
    } 

    handleUserInput({conditionTitleInput}) { 
    this.setState({ 
     conditionTitle:conditionTitle 
    }) 

    } 

    render() { 
    const {error, segmentId} = this.props; 

    return (
     <div> 

    <AddConditionSelect segmentId={segmentId} conditionTitle={this.state.conditionTitle} onUserInput={this.handleUserInput} /> 


    <PanelFooter theme="default"> 
     <Button backgroundColor="primary" color="white" inverted={true} rounded={true} onClick={(event) => this.onSubmit(event)}> 
     Next Step 
     </Button> 
    </PanelFooter> 

     </div> 
    ); 
    } 

} 

export default AddConditionDashboard; 

Детский компонент:

class AddConditionSelect extends React.Component { 

    onInputChange: function() { 
    this.props.onUserInput(
     this.refs.conditionTitleInput.value, 
    ) 
    }, 

    render() { 
    const {error} = this.props; 

    return (
     <div> 

     <Panel theme="info"> 

     <Divider /> 

     Please enter a name {error ? <Message inverted={true} rounded={true} theme="error">{error}</Message> : null} 
      <Input value={this.props.conditionTitle} ref="conditionTitleInput" label="" type="text" buttonLabel="Add Condition" name="add_segment" onChange={this.onInputChange} placeholder="Condition Title"/> 

     </Panel> 
    </div> 
    ); 
    } 

} 
export default AddConditionSelect; 
+1

вы можете показать нам свой входной компонент? Это поможет. – QoP

+0

Входной компонент - это только компонент Rebass - http://jxnblk.com/rebass/#Input – Dan

ответ

5

Как о прохождении обработчик события непосредственно <Input>? Таким образом, вы передаете на изменениях события непосредственно к родителю (прародитель <Input>), и вы можете извлечь значение из event.target.value поэтому нет необходимости использовать реф:

Примечания: Вы, возможно, придется bind контекста onUserInputChange() в вы конструктора родителя, потому что обработчики событий имеют элемент, на котором произошло событие, как их контекст по умолчанию:

Родитель

class AddConditionDashboard extends React.Component { 

    constructor(props) { 
    // ... 

    // bind the context for the user input event handler 
    // so we can use `this` to reference `AddConditionDashboard` 
    this.onUserInputChange = this.onUserInputChange.bind(this); 
    } 

    onUserInputChange({ target }) { 
    const { value: conditionTitle } = target; 
    this.setState({ 
    conditionTitle 
    }); 
    } 

    render() { 
    // ... 

    <AddConditionSelect segmentId={segmentId} 
         conditionTitle={this.state.conditionTitle} 
         onUserInputChange={this.onUserInputChange} // <-- pass event handler to child that will pass it on to <Input> 
    /> 

    // ... 
    } 
    // ... 

Ребенок:

class AddConditionSelect extends React.Component { 

    render() { 
    const { error } = this.props; 

    return (
     <div> 
     // ... 

     <Input value={this.props.conditionTitle} 
       label="" 
       type="text" 
       buttonLabel="Add Condition" 
       name="add_segment" 
       onChange={this.props.onUserInputChange} // <-- Use the grandparent event handler 
       placeholder="Condition Title" 
     /> 

     // ... 
    </div> 
    ); 
    } 
} 
+0

спасибо за супер подробный ответ! Теперь это намного яснее. Тем не менее, дочерний компонент с вводом теперь отображается корректно (без ошибок), но я не могу заполнить поле ввода (хотя ошибки в консоли все же). Я предполагаю, что это имеет какое-то отношение к двухстороннему связыванию, которое я делал в предыдущей версии дочернего компонента ... – Dan

+1

@ Dan Не беспокойтесь, рад помочь :). Кстати, что именно вы подразумеваете под «Я не могу заполнить поле ввода»? – nem035

+0

Спасибо :) Ввод текста в поле ввода не влияет. После комментирования части моего конструктора, которая устанавливает состояние 'this.state = {conditionTitle: ''}', поле ввода затем может быть заполнено. Однако console.logging внутри 'onUserInputChange()' не имеет никакого эффекта - так что это похоже на то, что функция не срабатывает при изменении ввода. : S – Dan

0
  1. Вам не нужно реф. значение может быть извлечено из события. Таким образом, ваш компонент для детей становится проще.
  2. Вы также можете упростить код, используя value link pattern.

    класс AddConditionDashboard расширяет React.Component { конструктор (реквизит) { super (реквизит);

    this.state = { 
        conditionTitle: '', 
        conditionType: '' 
    }; 
    

    }

    визуализации() { Const {ошибка, segmentId} = это.реквизит;

    return (
        <div> 
    
        <AddConditionSelect segmentId={segmentId} conditionTitle={ Link.state(this, 'conditionTitle') } /> 
    
    
        <PanelFooter theme="default"> 
        <Button backgroundColor="primary" color="white" inverted={true} rounded={true} onClick={(event) => this.onSubmit(event)}> 
         Next Step 
        </Button> 
        </PanelFooter> 
    
        </div> 
    ); 
    

    }

    }

    экспорта по умолчанию AddConditionDashboard;

И ребенок компонент

const AddConditionSelect = ({ error, valueLink }) => (
    <div> 

    <Panel theme="info"> 

    <Divider /> 

    Please enter a name { error ? 
          <Message inverted={true} rounded={true} theme="error"> 
           {error} 
          </Message> : null } 
     <Input value={ valueLink.value } 
       onChange={ e => valueLink.set(e.target.value) } 
       label="" type="text" 
       buttonLabel="Add Condition" name="add_segment" 
       placeholder="Condition Title"/> 

    </Panel> 
    </div> 
); 

export default AddConditionSelect; 
Смежные вопросы