-1

Hello i've been trying to implement componentDidUpdate. But i have a problem. But i think im doing some part correct, like i have the If statement required? im pretty sure this worked like 2 hours ago but now it's looping in the console. what am i missing?

I will start by posting the most relevant info from my component. I also have CRUD in my component. The view is updating fine after every change but with a downside of a loop from componentDidUpdate that wont stop.

i Would appreciate some help on this matter i've tried to do some research, i guess i should not call the API again? but how can i fix this issue.

i will only post the relevant code from my component.

enter code here

state = { productList: [], statusMsg: "", };

  // READ FROM API
  getDataFromProductsApi() {
    axios
      .get("https://localhost:44366/api/Products/")
      .then((res) => {
        console.log(res.data);
        this.setState({
          productList: res.data,
        });
      })
      .catch((error) => {
        console.log(error);
        this.setState({ statusMsg: "Error retreiving data" });
        if (axios.isCancel(error)) return;
      });
  }

  componentDidMount() {
    this.getDataFromProductsApi();
  }

  // reupdate the state on Changes
  componentDidUpdate(prevProps, prevState) {
    console.warn("changes");
    if (prevState.productList !== this.state.productList) {
      axios.get("https://localhost:44366/api/Products/").then((res) => {
        console.log(res.data);
        this.setState({
          productList: res.data,
        });
      });
    }
  }

//Post axios .post("https://localhost:44366/api/Products/", this.state) .then((response) => { console.log(response); this.setState({ statusMessage: "Product Added" }); }) .catch((error) => { console.log(error); this.setState({ statusMessage: "Something went wrong" }); if (axios.isCancel(error)) return; }); };

  // DELETE FROM API
  deleteProduct = (productId, productName) => {
    if (window.confirm("Are you sure? you want to delete")) {
      axios
        .delete(`https://localhost:44366/api/Products/${productId}`)
        .then((response) => {
          console.log(response);
          this.setState({
            statusMsg: `Product name: ${productName} With the ID: ${productId} was removed!`,
            //updating state to show the changes in view instantly
            //  productList: this.state.productList.filter(
            //  (item) => item.id !== productId
            //),
          });
        });
    }
  };
M R
  • 17
  • 8
  • That `prevState.productList !== this.state.productList` will always `return true` because they are arrays – TheLastStark Nov 13 '20 at 04:44
  • i see, how can i fix this issue? – M R Nov 13 '20 at 04:46
  • Try `JSON.stringify(prevState.productList) == JSON.stringify(this.state.productList)`. Or lodash equality functions will also be great. – TheLastStark Nov 13 '20 at 04:46
  • i dont know what lodash equality is but:D i get error with the Json you meant to replace ifstatement with that? – M R Nov 13 '20 at 04:50
  • no, it will be like `if(JSON.stringify(prevState.productList) == JSON.stringify(this.state.productList))` It should be inside the `if()` – TheLastStark Nov 13 '20 at 04:50
  • tried it something seems to work but. i think the problem starts when the list is empty and i refresh it starts to loop. now when i added this . when i remove an item it delets without refresh but when i add i have to refresh now – M R Nov 13 '20 at 04:57
  • sorry, it should be `if(JSON.stringify(prevState.productList) != JSON.stringify(this.state.productList))` – TheLastStark Nov 13 '20 at 05:08
  • it does'nt loop but i doesnt update the state either i have to refresh now after adding and deleting – M R Nov 13 '20 at 05:11
  • May I ask why are you updating the state in the `componentDidUpdate()` instead of directly settings it using `this.setState()`? – TheLastStark Nov 13 '20 at 05:17
  • its like the condition never gets true now? – M R Nov 13 '20 at 05:17
  • you can see the "changes" log, but not data? – TheLastStark Nov 13 '20 at 05:20
  • exactly. i se the log but it doesnt seem to call the componentdidupdate – M R Nov 13 '20 at 05:21
  • what do u mean now aint i doing this.setstate? u want me to remove the axios call? i simply just want to refresh the UI without refreshing page manually – M R Nov 13 '20 at 05:22
  • when adding new item or removing, are you updating the `this.state.productList` too? Can you show the adding, deleting methods too – TheLastStark Nov 13 '20 at 05:24
  • i added them to the original post the POSt/Delete. the post to api is in another component – M R Nov 13 '20 at 05:28
  • my delete function got a code for updating ui which is commented out . but i went for componentdidupdate because i wanted to try updating the ui like that . – M R Nov 13 '20 at 05:30
  • thanks, you need to update the `this.state.productList` using `this.setState()` when adding, updating and deleting, otherwise `prevState.productList ` will always be equal to `this.state.productList` that is why it is not rendering – TheLastStark Nov 13 '20 at 05:33
  • how can i do it when adding?. i already have it for Deleting but when adding i dont have the id – M R Nov 13 '20 at 05:36
  • im using thsi filter method when deleting and it works productList: this.state.productList.filter( (item) => item.id !== productId – M R Nov 13 '20 at 05:37
  • yeah deleting is correct, adding also can be done using `[...this.state.productList, newProduct]`. The id can be generated using `uuid`. – TheLastStark Nov 13 '20 at 05:45
  • but you don't even have to add a new one correctly, you just need to make sure that the current state of the `this.state.productList` has changed, because that is what causes the component to get new `productList` from the server and update the state. – TheLastStark Nov 13 '20 at 05:46
  • even tho the create is in another component and knows nothing about the list? – M R Nov 13 '20 at 05:49
  • yeah, if you are expecting this component to update when you make changes in the other component – TheLastStark Nov 13 '20 at 05:55
  • never worked with uuid etc:D – M R Nov 13 '20 at 06:01
  • As I said, you don't even have to actually have a proper ID, you just need to trigger an update, so adding a fake ID would do the trick. But, if you want to do it properly I suggest, in the server, after making a successful post request to add a new product, return the newly created product as the response, and then add that to the component state. – TheLastStark Nov 13 '20 at 06:05

1 Answers1

0

Since arrays are objects in JS, two arrays are equal only is they reference the same value(not different instances of that same value).

So using === and !== to compare arrays would be wrong.

console.log([1, 2] === [1, 2])   // returns false

let obj1 = {
    name: 'Disney'
};

let obj2 = {
    name: 'Disney'
}

console.log(obj1 === obj2);    // returns false

console.log([obj1] == [obj2]);  // returns false; 

So, I guess the problem is here in (prevState.productList !== this.state.productList)

You could refer to this answer for more on How to compare arrays in JavaScript?

Harshit Gangwar
  • 553
  • 7
  • 14