0

I have a global variable

const initialProductState = {
   id: 0,
   name: '',
   price: 0,
   rating: 0
}

I am using it to set state in my Products component as

state = {
     product : initialProductState
}

And when I am calling a method(addProduct) which is using initialState to set the current state to initial from another component(ProductDetail), it unexpectedly updates initialProductState. I am unable to find the reason for this update. Here's my code :

Products component :

class Products extends Component {
constructor(props){
    super(props);
    this.state = {
        product: initialProductState,

    }
}
addProduct = (product) => {
    const newProduct = {
      ...product,
      id : this.state.totalProducts + 1,
    } 
    console.log(" initialProductState ", initialProductState)
    this.setState({
      products : newProductsArray,
      totalProducts : this.state.totalProducts + 1,
      product : initialProductState
     })

}
}
render(){
   return 
      <ProductDetail
            product={this.state.product}
            addProduct={this.addProduct}
            saveProduct={this.saveProduct}
            deleteProduct={this.deleteProduct}
            cancelProduct={this.cancelProduct}
        />
 }

ProductDetail component :

class ProductDetail extends React.Component {
   state = {
    product: initialstate,
    priceError: "",
    nameError: "",
    ratingError: ""
  }
  static getDerivedStateFromProps(props, state) {
    console.log("inside getDerivedStateFromProps")
    if (props.product !== state.product) {
        return {
            product: props.product
        };
    }
    // Return null to indicate no change to state.
    return null;
  }
  render() {
     return (
        <Button
           variant="contained"
           color="primary"
           disabled = {!(this.props.product.id === 0)}
           onClick={() => {
               this.props.addProduct({
               name: 'random',
               price: 10,
               rating: 5
           })}
           }
        >
        Add
        </Button>
     )
 }
}
Mohit kumar
  • 447
  • 2
  • 10

1 Answers1

5

It's because of shallow copy. Most efficient way to deep clone Deep clone

change your code.

constructor(props){
    super(props);
    this.state = {
        product: JSON.parse(JSON.stringify(initialProductState)),

    }
}
akhtarvahid
  • 9,445
  • 2
  • 26
  • 29
  • 1
    `product: {... initialProductState}`. although it shouldn't be used if the object has nested objects. – Ahmed Eid Dec 16 '19 at 05:02
  • exactly. but state should be as flat as possible. – Ahmed Eid Dec 16 '19 at 05:05
  • @VahidAkhtar help me to understand one thing. I am updating the state after console.log(initialProductState). It means that during console.log instruction execution, the state is not updated and have its initial values. initialProductState must be updated when I update the state according to shallow copy. Then why it is updating before the update of state. – Mohit kumar Dec 17 '19 at 07:30
  • 1
    @mohitkumar because you are updating reference. whether you update state or not it will affect original object. it's concept of object. – akhtarvahid Dec 17 '19 at 08:38