通过道具将值从React Stateless Child传递给Parent

时间:2016-05-31 20:00:51

标签: javascript reactjs ecmascript-6

CONTEXT

我试图将输入值字段(conditionTitle)从React无状态子组件(AddConditionSelect)传递到将保存我的状态的父组件(AddConditionDashboard) 。

问题

我遵循React documentation中显示的模型,但他们使用的是refs,只有在组件有状态时才有效。我不想在子组件中设置任何状态,但仍然可以访问父组件中的输入。

在目前的形式中,我得到一个警告,无状态函数组件不能被赋予refs,导致props为null和undefined。

父组件:

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;

2 个答案:

答案 0 :(得分:6)

如何将事件处理程序直接传递给<Input>?这样您就可以将on change事件直接传递给您的父级(祖父母<Input>),并且您可以从event.target.value中提取值,因此无需使用refs:

注意:您父母的构造函数中可能必须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>
    );
  }
}

答案 1 :(得分:0)

  1. 你不需要参考。可以从事件中提取值。因此,您的子组件变得更简单。
  2. 您可以使用value link pattern进一步简化代码。

    类AddConditionDashboard扩展了React.Component {   构造函数(道具){     超级(道具);

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

    }

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

    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;

  3. 和儿童组件

    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;