0
import React, { useEffect, useState } from 'react';
import axios from "axios";
import './List.css';
import { toast } from "react-toastify";

const List = () => {
  const url = "http://localhost:4500";

  const [list, setList] = useState([]);

  const fetchList = async () => {
    const response = await axios.get(`${url}/api/food/list`);
    console.log("the response data", response.data);
    if (response.data.success) {
      
      setList(response.data.data)
    }
    else {
      toast.error("error")
    }
  }


  useEffect(() => {
    fetchList();
  }, []);

  useEffect(() => {
    console.log("the list type: ", typeof (list));
  }, [list]);

  return (
    <div className='list add flex-col'>
      <p>All food List</p>
      <div className="list-table">
        <div className="list-table-format title">
          <b>Image</b>
          <b>Name</b>
          <b>Category</b>
          <b>Price</b>
          <b>Action</b>
        </div>
        {list.map((item,index)=>{
          return(
            <div key={index} className="list-table-formate">
              <p>{item.name}</p>
            </div>
          )
        })}
      </div>
    </div>
  );
};

export default List;

In the above code I fetch the data from backend using useState([]) empty dependency array using fechList() function. The data is fetched successfully. But still the list seems to be empty. If someone knows the reason, please discuss with me.

I expect the list to be printed in front-end and showing the data properly.

2
  • Instead of if...else, use try....catch. Could you share the response from backend if fetched successfully? Commented Jul 9 at 4:46
  • try/catch for an error with undefined is overkill. You need to find the root cause of the error and either fix your code if that is the problem or add handling for cases where the returned data is not defined. Commented Jul 10 at 9:35

3 Answers 3

1

here are the issues with your response.data.data It must be an array but sometimes it gets null or undefined so you can do is to add OR condition with empty array.

if (response.data.success) {
  setList(response.data.data || [])
}

here in this case if response.data.data is a falsy value it will take an empty array and it will prevent the error.

or the second option is to check the length and use '?' returns undefined instead of throwing an error.

{list && list.length > 0 && list?.map((item,index)=>{
          return(
            <div key={index} className="list-table-formate">
              <p>{item.name}</p>
            </div>
          )
        })}
0

From your code, it seems like you're new to React and issues like these are handled in a certain manner. What improvements does it require?

  • A try-catch block or exception handling, so if the API is incase not returning anything or returning errors, you can log them in the console (console.log()) to get an idea.
  • A loader or loading indicator, so the return codes know when to return the views or visible elements, it will wait for the API fetching to be done and then return the elements or lists as received from API response.

An updated, proper and scalable code will look something like this-

import React, { useEffect, useState } from 'react';
import axios from "axios";
import './List.css';
import { toast } from "react-toastify";
import ClipLoader from "react-spinners/ClipLoader"; // Import a spinner loader to indicate users that it's loading

const List = () => {
  const url = "http://localhost:4500";

  const [list, setList] = useState([]);
  const [isLoading, setIsLoading] = useState(true); // Add isLoading state to control the loader or loading

  const fetchList = async () => {
    // Use try catch finally block for API handling
    try {
      const response = await axios.get(`${url}/api/food/list`);
      console.log("the response data", response.data);
      if (response.data.success) {
        setList(response.data.data);
      } else {
        toast.error("Error fetching data");
      }
    } catch (error) {
      toast.error("Error fetching data");
    } finally {
      setIsLoading(false); // Set isLoading to false after data is fetched
    }
  };

  useEffect(() => {
    fetchList();
  }, []);



  return (
    <div className='list add flex-col'>
      <p>All Food List</p>
      {isLoading ? ( // Conditionally render the loader
        <div className="loader">
          <ClipLoader size={50} />
        </div>
      ) : (
        <div className="list-table">
          <div className="list-table-format title">
            <b>Image</b>
            <b>Name</b>
            <b>Category</b>
            <b>Price</b>
            <b>Action</b>
          </div>
          {list.map((item, index) => (
            <div key={index} className="list-table-format">
              <p>{item.name}</p>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export default List;

If you still have any queries, leave a comment, I'll help.

-1

The only thing that comes to my mind is that the response structure is different that the one that you expect here

enter image description here

try to check the response and see if it is 'data.data'

3
  • yes have to check the response it's data.data. Commented Jul 9 at 7:14
  • if i insert setList(response.data.data) so list is empty when i console it using useEffect Commented Jul 9 at 7:16
  • and 'response.data.success'? try to console.log that and see if you get the correct value, maybe is not entering in the if statement
    – Yuu
    Commented Jul 9 at 14:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.