简体   繁体   中英

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM