简体   繁体   中英

How to get data from props.children to its parent in ReactJS?

I'm trying to get data from a props.children [Input] to it's parent [Form], to build an all in one form component. I am currently stuck at getting data to Input component to Form component.

This is what i have done so far =>

edit.js =>

export default class Edit extends Component {

    constructor(props) {
        super(props)
        this.state = {
            formFields: {
                name: '',
                email: ''
            }
        }
    }

    render() {
        return (
            <Form
                id={ this.props.match.params.id }
                onReceiveFormData={ this.onFiledDataChange.bind(this) }
            >
              <Input
                label='name'
                name='name'
                value='some'
              />
              <Input
                label='email'
                name='email'
                value='email@gmail'
              />
            </Form>
        );
    }
}

Input.js =>

export default class Input extends Component {

    constructor(props) {
        super(props)
        this.state = {
            value: this.props.value
        }
    }

    static setValue(val) {
        return val ? val : ''
    }

    handleInputChange = (event) => {
        this.setState({
            value : event.target.value
        })
        this.props.onInputChange({
            [event.target.name] : event.target.value
        })
    }

    render() {
        return (
            <input
                name={ this.props.name }
                value={ Input.setValue(this.state.value) }
            />
        );
    }
}

Form.js =>

 export default class Form extends Component {

    constructor(props) {
        super(props)
    }


    saveClick() {
       /**
        Save logic => I want to get the field data here
       **/
    }

    render() {
        return (<div>
                 {
                    this.props.children
                  }
                  <Button
                      onClick={ () => this.saveClick() }
                     >Save</Button>
                 </div>
        );
    }
}

For example, If post -> edit page and user -> edit page => I would like to do setting the input value inside the Form.js, Form.js will be responsible for setting the values inside those Inputs when it is mounted and it will be responsible for sending the data to the server.

I would like to the know, the scenario I have suggest is possible or is there a better way to do it?

Invert control (make Input a controlled component). Keeping state inside components unnecessarily is generally a bad design practice. Look at the existing <input> it takes a value and an onChange . Your component should do too.

const Input = ({
  className,
  ...rest
}) => (
  <input
    className={classNames('Input', className)}
    type="text"
    {...rest}
  />
);

Then the parent has the state for when the form is submitted in Edit.

onFormSubmit = e => {
  e.preventDefault();
  console.log(this.state.name, this.state.email);
}

onChange = name => e => this.setState({ [name]: e.target.value })

// ...
<Input onChange={this.onChange('name')} value={this.state.name} />
<Input onChange={this.onChange('email')} value={this.state.email} />

If you want Form to listen in on state changes you could do this:

onChange = (e, originalOnChange) => {
  console.log('onChange called:', e.target.value);
  originalOnChange && originalOnChange(e);
}

// ...
const children = React.Children.map(this.props.children, child =>
  React.cloneElement(child, { onChange: e => this.onChange(e, child.props.onChange) })
);

It's a bit unorthodox but technically achievable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM