javascriptreactjsasync-awaitfetch-api

why is my code fetching the same items twice when the page is loaded?


I am learning React and trying to fetch some data for a product list.

It is supposed to fetch only 2 items at first and fetch 2 more items when pressing the button, but it is now fetching the same items twice when the page is loading at first.

import { useEffect, useState, Fragment } from 'react';
import './style.css';

export default function LoadMoreData() {
  const [loading, setLoading] = useState(false);
  const [products, setProducts] = useState([]);
  const [count, setCount] = useState(0);
  const [disableButton, setDisableButton] = useState(false);

  const loadLimit = 10;
  let limit = 2;

  async function fetchProducts() {
    const dataUrl = `https://dummyjson.com/products?limit=${limit}&skip=${
      count === 0 ? 0 : count * limit
    }`;

    try {
      setLoading(true);
      const response = await fetch(dataUrl);
      const result = await response.json();

      if (result && result.products && result.products.length) {
        setProducts((prevData) => [...prevData, ...result.products]);
        setLoading(false);
      }

      console.log(result);
    } catch (e) {
      console.log(e);
      setLoading(false);
    }
  }

  useEffect(() => {
    fetchProducts();
  }, [count]);

  useEffect(() => {
    if (products && products.length === loadLimit) setDisableButton(true);
  }, [products]);

  if (loading) {
    return <div>Loading data! Please wait.</div>;
  }

  return (
    <Fragment>
      <div className='load-more-container'>
        <div className='product-container'>
          {products && products.length
            ? products.map((item) => (
                <div className='product' key={item.id}>
                  <img src={item.thumbnail} alt={item.title} />
                  <p>{item.title}</p>
                  <span>$ {item.price}</span>
                </div>
              ))
            : null}
        </div>
        <div className='button-container'>
          <button disabled={disableButton} onClick={() => setCount(count + 1)}>
            Load more products
          </button>
          {disableButton ? (
            <p>You have reached to {loadLimit} products!.</p>
          ) : null}
        </div>
      </div>
    </Fragment>
  );
}

I thought the bug maybe because I put the async function outside the useEffect, but still couldn't solve the problem even though put it in the useEffect

can anyone give me a hint where the bug would be? Thank you


Solution

  • You most likely need to remove <React.StrictMode> from your index.js file. Possible duplicate of React Hooks: useEffect() is called twice even if an empty array is used as an argument