0

Why child state data change updates parent state data?

I want to update parent data only after child form is complete.

export default class StepOne extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            data: this.props.data
        }
        this.handleChanges = this.handleChanges.bind(this);
    }
    handleChanges(e){
        var data = this.state.data
        console.log(this.props.data) //{loan_amount: "", validate: false}
        var name = e.target.name
        var value = e.target.value
        data[name] = e.target.value
        this.setState({data})
        console.log(this.props.data) //{loan_amount: "1", validate: false}
    }
    render() {
        return (
            <div>
                <h4 className="form-ques">Loan Details</h4>
                <Row>
                    <Input label="Required Amount" type="number" name="loan_amount" onChange={this.handleChanges} value={this.state.data.loan_amount}/>
                </Row>
            </div>
    )}
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400

3 Answers3

1

From your question it is not obvious what is your parent component or your child component. If this code represents your child component, then you need to move the handleChanges(e) to the parent component because now you are setting the child state, instead of the parent state.

basifat
  • 19
  • 3
1

The Reason that your parent state changes based on the child is that you are mutating the state and thus the props directly

constructor(props){
    super(props)
    this.state = {
        data: this.props.data .  // <-- props are assigned to state by reference here
    }
    this.handleChanges = this.handleChanges.bind(this);
}
handleChanges(e){
    var data = this.state.data .  // <-- the state data and thus the prop data are assigned to data by reference here
    console.log(this.props.data) //{loan_amount: "", validate: false}
    var name = e.target.name
    var value = e.target.value
    data[name] = e.target.value // <-- since data references state and prop directly you are modifying them both by modifying data.
    this.setState({data})
    console.log(this.props.data) //{loan_amount: "1", validate: false}
}

The solution is simple, you need to clone the object state data instead of directly assigning it using spread syntax

handleChanges(e){
    var data = {...this.state.data} //Spread syntax creates a new object for you 
    console.log(this.props.data) 
    var name = e.target.name
    var value = e.target.value
    data[name] = e.target.value
    this.setState({data})
    console.log(this.props.data) 
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0

Rather then doing it like this you can do something like this

export default class StepOne extends React.Component{
constructor(props){
   super(props)
   // You don't need the state here
   //this.state = {
   // data: this.props.data
   //}
   this.handleChanges = this.handleChanges.bind(this);
}

// you don't need this here as well
handleChanges(e){
   //var data = this.state.data
   //console.log(this.props.data) //{loan_amount: "", validate: false}
   //var name = e.target.name
   //var value = e.target.value
   //data[name] = e.target.value
   //this.setState({data})
   //console.log(this.props.data) //{loan_amount: "1", validate: false}
}

render() {
    const { loan_amount, validate } = this.props.data;
    return (
      <div>
        <h4 className="form-ques">Loan Details</h4>
        <Row>
          <Input 
           label="Required Amount" 
           type="number" 
           name="loan_amount" 
           onChange={this.props.onHandleChange} //New method to change value 
           value={loan_amount} // Getting this value from props
          />
       </Row>
     </div>
)}

Then in your parent class where you have defined everything you create a function called.

onHandleChange = (e) => {
   var data = this.state.data;
   data[e.target.name] = e.target.value;
   this.setState({ data });
}

This way every time you change your child component, only one data field is change that being in your parent component, and your parent component is the one updating/changing the form.

I hope it helps please do let me know if you still have any questions.

Adeel Imran
  • 13,166
  • 8
  • 62
  • 77
  • Can you tell me how my code is updating parent state data? – Abhinav Rai Oct 03 '17 at 06:38
  • In your handleChange event the consoles that your logging are not correct, it is not possible that you change something in your Child component and without linking it with the Parent component via a function. That the Parent state value changes. You need to share the entire code for someone to tell you why this is happening the way it is. – Adeel Imran Oct 03 '17 at 06:47
  • that's what bothers me too. see @Shubham Khatri answer. – Abhinav Rai Oct 03 '17 at 06:56
  • Yeah saw it, :) Great. – Adeel Imran Oct 03 '17 at 06:59