Dignity Dignity
Dignity Dignity

Reputation: 151

Functional component is not rerendering after state is changed

I would like to ask why my component is not rerendering after my state is changed and I need to refresh it (switch between routes) to see changes. Well, the interesting fact is that the first time when I click the delete button page (component) does not rerender but after I switch routes and come back the item is deleted and when I try to delete other items, it gets deleted instantly not like the first time.

This is my code:

import React, {useEffect, useState} from 'react';
import ApiFactory from '../mock';
import Editor from '../Editor';
import ProductCard from '../components/product-card/product-card';
import ProductEdit from '../components/product-edit/product-edit';

export default function Admin() {
  const [items, setItems]= useState([]);
  useEffect(() => {
    getProducts();

  }, [items]);

  function getProducts() {
    ApiFactory.getInstance().get('/api/products')
      .then((res) => {
        if(res.status == 200) {
          setItems(res.data);     
        }
      })
      .catch((error) => { console.log(error)}) 
  }

  function handleDelete (productId) {
    ApiFactory.getInstance().delete(`/api/products/${productId}`)
     .then(()=> getProducts()
    );
  }

  return (
    <>
     {
      items.map((item, index) => {
        console.log(item.id)
        return <>
          <div key={index}>
            <ProductCard product={item}></ProductCard>
            <button onClick={() => handleDelete(item.id)}>Delete</button>
          </div>
          </>
      }) 
    }
    </>
  );
}

I am quite new in React can anybody explain why it happens and how can I fix it?

Upvotes: 1

Views: 92

Answers (1)

Oliver
Oliver

Reputation: 237

I believe it's because of how you have useEffect set up.

  1. change the useEffect to only make the GET API call once (on initial load):

    useEffect(() => {
        getProducts();
    
      }, []); // remove the dependency here. You may have made an infinite        loop here.
    
      const getProducts = () => {
        ApiFactory.getInstance().get('/api/products')
          .then((res) => {
            if(res.status == 200) {
              setItems(res.data);    
            }
          })
          .catch((error) => { console.log(error)}) 
      }
    

If you confirmed that the API call is handling your errors / successes (are you getting non 200 status codes ? those may not be handled)

  1. Add error catching to handleDelete to make sure this call works.

    const handleDelete = (productId) => {
        ApiFactory.getInstance().delete(`/api/products/${productId}`)
        .then(getProducts())
        ).catch((error) => { console.log(error)}) 
    }
    

You may additionally do as another user suggested and move even more logic away from the API calls (not required though) to have state locally and not re-fetch data from the API.

Upvotes: 1

Related Questions