Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

207
Views
React useState changes all elements in an array in array of objects

I have 2 states product and variations I call an API and set the values of both state to the API response.

I want the product state to stay as it is and not update

  const [product, setProduct] = useState({} as any);
  const [variations, setVariations] = useState([] as any);

  useEffect(() => {
    const getProduct = async () => {
      const data = await axios.get("/products?id=4533843820679");
      console.log(data);
      setProduct(data.data);
      // @ts-ignore
      setVariations([data.data]);
    };
    getProduct();
  }, []);

In return I map the variations array and return inputs for title, and price and a button to add variations. Adding variations will add another product to variations array. So it just pushes product to variations.

Then I have inputs for title in variation and prices in variation.variants. The problem is with onChange.

When I change the price of one element in variants it changes for all and also changes it for PRODUCT state.

The code can be found here: https://codesandbox.io/s/smoosh-firefly-6n747?file=/src/App.js

Add variations, change prices add another variations and you'll see all issues I'm facing.

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

It is because of this:

 variant.price = e.target.value; // same issue with title

the variant object reference is shared among variations and you are modifying it directly. It is shared because you you made a shallow copy of a variation using ... when adding it.

Here is the solution:

You should update the specific variant object in immutable way (in react you should always update state in immutable way). For that you need to use this as onChange for price:

onChange = {
    (e) => {
        let updated = variations.map((x) => {
            if (x.id === variation.id) {
                return {
                    ...x,
                    variants: x.variants.map((y) => {
                        if (y.id === variant.id) {
                            return {
                                ...y,
                                price: e.target.value
                            };
                        }
                        return y;
                    })
                };
            }
            return x;
        });
        setVariations(updated);
    }
}

This for onChange for title:

onChange = {
    (e) => {
        let updated = variations.map((x) => {
            if (x.id === variation.id) {
                return {
                    ...x,
                    title: e.target.value
                };
            }
            return x;
        });
        setVariations(updated);
    }
}

NOTE but ids of variations must be different. For testing purposes you can use this as click handler when adding a new variation:

onClick = {
    () => {
        setVariations((prev) => [...prev, {
            ...product,
            id: Math.floor(Math.random() * 1000) // for testing
        }]);
    }
}
about 4 years ago · Juan Pablo Isaza Report

0

First, you are not pushing the product to variations. You are overwriting it.

To push a value to array with useState,

setVariations([...variations, product])

But, if you change the product object, variations also gonna be change because it's the same object. (Maybe, react not gonna re-render it but trust me, it is changed.) If you want to keep it same you need to create new object.

So,

setProduct(data.data);
setVariations([...variations, {...data.data}]);

Now, you can change product. variations not gonna change.

about 4 years ago · Juan Pablo Isaza Report

0

This was because you did a shallow copy of an object.

Try to do like this:

setVariations([...variations, data.data,]);
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!