Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

TypeError: Cannot assign to read only property 'value' of object react after using the value of state in a function

I am trying to develop an E-commerce website with a product detail page. Users may select available options of the product. Supposed I choose a shoe and selected size 42, when I click "Add to Cart" button, it triggers handleAddToCart once. When that is done, if the user wants to add different variations he can just click on differentVariationBox and then again click "Add to Cart" and this should add the newly selected product to cart

The error comes only after handleAddToCart is executed and handleVariation will cause an error. I would like to know why this error is happening and how to solve it.

When I try to change the product option I got the following error

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

enter image description here

const handleAddToCart = () => {

  // The selected variation is an array which track the selected attributes but its 
  // order depends on the user click on the attributeswe need to sort them in the order we have 
  // Received from the server because we will create an unique key for the cart item to know if the 
  // Product is alredy in cart with same attributes

  // 😎 example i order shoe with id black-puma with size 42 and color black

  // The id will become black-puma+size=42+color=black now i can track weather this variation product exist

  const order = product.attributes.map((attribute) =>
    this.state.selected_variation.find((v) => v.type === attribute.id)
  );
  
  // Checking if the length of the variation is equal to the length of the attributes
  // This will ensure all the variation is selected
  if (this.state.selected_variation.length ===product.attributes.length) {
    const data = {
      variation: order,
      product: product,
      quantity: this.state.quantity,
      id:`${product.id}+${order.map((item) => `${item.type}=${item.value}`).join("+")}`
    };
    this.props.addToCart(data);
    
  } else {
    alert("Please Select all the variations or The selected variation is already exist in the cart");
  }
};



// Function that will handle the variation selection
    const handleVariation = (e) =>{
      let type = e.target.name;
      let value = e.target.value;

      // Checking is the selected attribute exist
      let index = this.state.selected_variation.findIndex((x)=>{
        return x.type === type
      })
       // if not exist then add it
       if(index === -1){
        this.setState({
          selected_variation: [...this.state.selected_variation, {type,value}]
        })
      }else{
        const newData = [...this.state.selected_variation];
        
        newData[index].value = value
        this.setState({
          selected_variation:newData,
        })
      }
    }

SO Handle variation triggered when enter image description here

Any of the variation is change handleVariation will be trigger when there is change in input radio state

>Solution :

Problem with your code is here:

else{
    const newData = [...this.state.selected_variation];
    
    newData[index].value = value
    this.setState({
      selected_variation:newData,
    })
  }

First, you copied old state using spread. Like that you just created new array, but array elements are referencing to that same element from the current state (reference is unmodified since you shallowly copied only array on the top level). After that you accessed element with index, and since elements in array were not copied newData[index] reference element directly from this.state. Since you are trying to mutate state directly react will throw you an error, it won’t let you do that because it expect to mutate only using this.setState.

Rewrite to this:

 else{
    this.setState(prevState => ({selected_variation: 
      prevState.selected_variation.map((el, ind) => ind === index ? { ...el, value} : el })
  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading