indrjit kumar
indrjit kumar

Reputation: 33

How to pass Child Component's form value to Parent Component

Is there a way to pass form data from child component to Parent component, where submit buttons have been kept in parent component.

NOTE: - I don't want to use ref for this as the ref would be waste of so much of memory and I might have 6-7 children in the parent.

I have created a similar situation to show what I am stuck on.

class FirstChildForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    render() {
        return (
            <div className="form">
                <input type="text" placeholder="Enter your name..." />
                <input type="password" placeholder="Enter password" />
            </div>
        )
    }
}


class SecondChildForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    render() {
        return (
            <div className="form">
                <input type="text" placeholder="Enter your name..." />
                <input type="password" placeholder="Enter password" />
            </div>
        );
    }
}



export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    handleSubmit = () => {

    }

    render() {
        return (
            <div className="parent">
                <FirstChildForm />
                <SecondChildForm />

                <button onClick={this.handleSubmit}> Submit</button>
            </div>
        )
    }
}

Upvotes: 3

Views: 3288

Answers (3)

Shubham Tiwari
Shubham Tiwari

Reputation: 2021

by passing a function to the child component as props and passing the child component's state as parameter to the function

as i dont know what you exactly want to code inside but only to understand checkout

following example

parent:

    export default class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      data: []
    }
  }


    handleSubmit = () => {

  }  
  handleData = (newData) => {
    this.setState({data: newData});
}

render(){
  return (
  <div className="parent">
  <FirstChildForm / >
  <SecondChildForm  onSelectData={this.handleData}/>

  <button onClick={this.handleSubmit}> Submit</button>
  </div>
  )
}
}

Child:

 class SecondChildForm extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      data:'hello'
    }
  }

  handleDataChange: function () {
    var newData = this.state.data
    this.props.onSelectData(newData);            
},

render(){
  return (
  <div className="form">
  <input type="text" placeholder="Enter your name..." />
  <input type="password" placeholder="Enter password" />
  <button onclick={this.handleDataChange}>submit</button>
  </div>
);
}
}

Upvotes: 1

Treycos
Treycos

Reputation: 7492

You will have to pass a function down to your children components. Your children will now be able to bind this function from their props to the given fields.

class FirstChildForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    render() {
        return (
            <div className="form">
                <input type="text" placeholder="Enter your name..." onChange={this.props.dataChanged('name')}/>
                <input type="password" placeholder="Enter password" onChange={this.props.dataChanged('password')}/>
            </div>
        )
    }
}


class SecondChildForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    render() {
        return (
            <div className="form">
                <input type="text" placeholder="Enter your name..." onChange={this.props.dataChanged('name')}/>
                <input type="password" placeholder="Enter password" onChange={this.props.dataChanged('password')}/>
            </div>
        );
    }
}



export default class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }

    handleChange = form => field => ev => {
        this.setState(prev => ({ [form]: { ...prev[form], [field]: ev.target.value } }))
    }

The resulting state of your parent will have the following structure :

{
    'firstForm': {
        'name': '',
        'password': ''
    },
    'secondForm': {
        'name': '',
        'password': ''
    }
}

Upvotes: 0

Predrag Beocanin
Predrag Beocanin

Reputation: 1400

Sure, the concept is called lifting the state up. Basically, your <App /> component would hold the data from both components. I'm going to simplify a bit, but you should understand what I'm doing.

FirstChildForm.js

<input type="text" name="username" onChange={e => props.updateData('user', e.target.value)}

SecondChildForm.js

<input type="password" name="password" onChange={e => props.updateData('pass', e.target.value)}

App.js

export default class App extends React.Component {
    constructor() {
        super();
        this.state = {
            user: '',
            pass: '',
        };
    }

    handleSubmit = () => {};

    updateData = (target, value) => {
        this.setState({ [target]: value });
    };

    render() {
        return (
            <div className="parent">
                <FirstChildForm updateData={this.updateData} />
                <SecondChildForm updateData={this.updateData} />

                <button onClick={this.handleSubmit}> Submit</button>
            </div>
        );
    }
}

The <App /> component is the source of truth. Please note:

By lifting the state up, <FirstChildForm /> and <SecondChildForm /> don't need to be class based components anymore, they can be functional components. If you want them to remain class based for whatever reason, change props.updateData to this.props.updateData, else it won't work.

The parent is where we define the function, the child is where we execute it, sending data to parent, basically!

Upvotes: 3

Related Questions