Reputation: 130
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>
)}
}
Upvotes: 0
Views: 148
Reputation: 281666
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)
}
Upvotes: 1
Reputation: 19
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.
Upvotes: 1
Reputation: 13966
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.
Upvotes: 0