0

I'm trying to get data from firebase/firestore using javascript so i made a function where i get my products collection and passing this data to reactjs state.products by setState() method

My goal is to pass these products to my react state but also keeping the original data and not changing it by manipulating it. I understand that in JavaScript whenever we are assigning the objects to a variable we are actually passing them as a reference and not copying them, so that' why i used the 3 dots (spread syntax) to copy firestore data into tempProducts[] same way to copy it in virgins[]

getData = () => {
    let tempProducts = [];
    let virgins = [];
    db.collection("products")
      .get()
      .then(querySnapshot => {
        querySnapshot.forEach(item => {
          const singleItem = { ...item.data() };
          virgins = [...virgins, singleItem];
          tempProducts = [...tempProducts, singleItem];
        });
        tempProducts[0].inCart = true;
        this.setState(
          () => {
            return { products: tempProducts };
          },
          () => {
            console.log(
              "this.state.products[0].inCart: " + this.state.products[0].inCart
            );
            console.log("tempProducts[0].inCart: " + tempProducts[0].inCart);
            console.log("virgins[0].inCart: " + virgins[0].inCart);
          }
        );
      });
  };

then calling this method in componentDidMount

componentDidMount() {
    this.getData();
  }

So I changed the first product inCart value in tempProducts to true when I console log tempProducts value and state.products value it gives me true all fine but I'm expecting to get false when i console log virgins value but i did not. I should also mention that all inCart values are false in firestore data.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • 1
    The spread operator does shallow copying, which means deep references will still remain intact during manipulating. You'll need to clone the object completely if you want to break all the references and get a true, unreferenced copy. – lux Aug 21 '19 at 18:11
  • The spread syntax doesn't clone nested properties or values. So you're just making new arrays, with the same Object references within them. – Emile Bergeron Aug 21 '19 at 18:14
  • Possible duplicate of [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – Emile Bergeron Aug 21 '19 at 18:15
  • Other possible duplicate (which deals specifically with modifying immutable arrays) [Correct modification of state arrays in ReactJS](https://stackoverflow.com/q/26253351/1218980) – Emile Bergeron Aug 21 '19 at 18:17
  • So i understand that i should also use the spread operator next to singleItem object like so `virgins = [...virgins, {...singleItem}];` right? – youness toubella Aug 21 '19 at 18:17
  • And [_How to update nested state properties in React_](https://stackoverflow.com/q/43040721/1218980), [_How do I update state.item on setState?_](https://stackoverflow.com/q/29537299/1218980) – Emile Bergeron Aug 21 '19 at 18:25
  • @Emile thanks i solved mine by passing this `virgins = [...virgins, item.data()];` instead of singleItem value – youness toubella Aug 21 '19 at 18:29
  • I updated the title to something closer to the question's description, feel free to change it to something else, granted it's relevant ;) – Emile Bergeron Aug 21 '19 at 18:29

1 Answers1

0

I solved the issue by passing the original firestore data to virgins[] instead of the singleItem as it is an object referenced by tempProducts[] like so virgins = [...virgins, item.data()]; also it works if i copied the singleItem object instead of referencing it like so virgins = [...virgins, { ...singleItem }]; keep in mind that i have no idea if this solutions are in fact efficient (not "memory waste") or not.