skip to Main Content

This should be simple, but I don`t know why it is failing.

I`m fetching data from an API with axios in React. The code is really simple:

import React, {useEffect, useState} from "react"
import axios from "axios";

export default function App() {

    const [items, setItems] = useState();

    useEffect(() => {
        axios.get("https://dummyjson.com/products/")

            .then((response) => {
                setItems(response.data);
            }).catch((error) => {
            console.log(error);
        });
    }, []);

    console.log(items);
}

This works right, and I get the reponse in the console:

console log

Now, if I change console.log(error); to console.log(error.products); at first works and I can see it too in the console:

console log 2

But, if I reload the page it stops working and shows error:

error screen

I have tried with the fetch inside and outside of useEffect, two useEffects, Api Fetch instead of Axios, but is always the same.

I will be very grateful for any kind of help.

5

Answers


  1. On the first render, the component sees the init state as undefined. Try to conditionally render all the components:

    if(!items) return null
    
    return the rest 
    

    Or, the easy solution, use an array as the initial state:

    const [items, setItems] = useState([]);
    
    Login or Signup to reply.
  2. You can verify whether the item is undefined. This is because, when reloading, the promise is still incomplete. A straightforward way to do this is:

    import React, {useEffect, useState} from "react"
    import axios from "axios";
    
    
    function App() {
      const [items, setItems] = useState();
    
      useEffect(() => {
          axios.get("https://dummyjson.com/products/")
    
              .then((response) => {
                  setItems(response.data);
              }).catch((error) => {
              console.log(error);
          });
      }, []);
    
      if (items === undefined) {
        return <div>Loading...</div>;
      } else if (items) {
        console.log(items.products);
      }
    }
    
    Login or Signup to reply.
  3. You can try the below code. I hope this helps!

    import React, { useEffect, useState } from "react";
    import axios from "axios";
    
    const App = () => {
      const [items, setItems] = useState([]);
    
      useEffect(() => {
        async function fetchData() {
          await axios
            .get("https://dummyjson.com/products/")
            .then((response) => {
              setItems(response.data);
            })
            .catch((error) => {
              console.log(error);
            });
        }
        fetchData();
      }, []);
      return (
        <div>
          {items?.products &&
            items?.products.map((item) => <p key={item.id}>{item.title}</p>)}
        </div>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
  4. You App component should return JSX like this:

    return (
        <div>
          {items &&
            items.products.map((product) => (
              <div key={product.id}>{product.title}</div>
            ))}
        </div>
      );
    

    Why? Because on initial render your items state’s undefined so JS couldn’t read products property of undefined and gave an error you mentioned. To avoid this, you need to check items for falsy value like above code.

    Login or Signup to reply.
  5. This issue might be related to the initial state of items. When you initialize items using const [items, setItems] = useState(), its initial value is undefined. When you try to access error.products in the catch block, it works the first time because there’s no data, and error itself is undefined. However, after the initial successful API call, the state is updated with the actual data, and subsequent API calls are not hitting the catch block, resulting in error being undefined.

    You can initialize items with an empty array or an empty object instead of undefined. This way, even if there’s no data, items won’t be undefined.

    const [items, setItems] = useState([]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search