-3

I am new to Reactjs. I am using React hooks and axios to fetch an api of a single post data from its id. I called the api and passed the data into child components using props through spread operator. The server runs but on the page it renders the above error. I have used the map function correctly, but it says map is not a function. I checked the issues online, where the users having similar problem says the data may not be an array. It should be an array but different data types like id,name,title,price etc in my case.

My FoodPage.js

function Food() {

  const [food, setFood] = useState([])
  const [id,setId] = useState(1)

  useEffect(() => {
    axios.get(`https://exampleurl.herokuapp.com/api/menus/${id}`)
    .then(abc=>{
      console.log(abc.data)
      setFood(abc.data)
    })
    .catch(err =>{
      console.log(err) 
    })
  }, [])


 return (
  <div>
    <div className="food-page">         
         {food.map((foodItem) => {
            return <PageHeader  {...foodItem} key={foodItem.id} />;
          })}
           <Customize />
          {food.map((foodItem) => {
            return <FoodDescription  {...foodItem} key={foodItem.id} />;
          })}       
    </div>
  </div>
  );
}

export default Food;

My FoodDescription:

function FoodDescription(props) {

  console.log(props);
  const {food_name,long_title,subtitle,description,price,id} = props;

  return (
    <div className="food-description">
        <div className="container">
          <div className="title">
            <div className="main-title">{food_name}</div>
          </div>
          <div className="description">
            {/* {description.map((des: string, index: number) => { */}
            {description.map((des, index) => {  
              return <p key={index}>{des}</p>;
            })}
          </div>
          <div className="order">
            <div className="quantity">
              <div className="negative" onClick={() => this.handleDecrement()}>
                -
              </div>
              {this.state.quantity}
              <div className="positive" onClick={() => this.handleIncrement()}>
                +
              </div>
            </div>
            <ExploreButton active="link-active">
              Add to Order -{price}
            </ExploreButton>
          </div>
        </div>
      </div>
  )
}

export default FoodDescription;

Update

The abc.data in console gives the following:

enter image description here

Reactoo
  • 916
  • 2
  • 12
  • 40

3 Answers3

2

According to your API result, when you call

https://texas-crm1.herokuapp.com/api/menus/1 it return an object, not an array.

{
    "id": 1,
    "category": "main courses",
    "image": "imgUrl",
    "image_url": "imgUrl",
    "food_name": "butter chicken",
    "subtitle": null,
    "long_title": null,
    "description": "<p>this is a test data from backend for butter chicken in main courses.</p>",
    "price": 49.0,
    "rating": 3.0
}

So you don't need to map over food try this :

function Food() {

  const [food, setFood] = useState([])
  const [id,setId] = useState(1)

  useEffect(() => {
    axios.get(`https://texas-crm1.herokuapp.com/api/menus/${id}`)
    .then(abc=>{
      console.log(abc.data)
      setFood(abc.data)
    })
    .catch(err =>{
      console.log(err) 
    })
  }, [])


 return (
  <div>
    <div className="food-page">         
       <PageHeader  {...food} key={food.id} />;
       <Customize />
       <FoodDescription  {...food} key={food.id} />;
    </div>
  </div>
  );
}

export default Food;
Sephyre
  • 326
  • 2
  • 13
  • For all the post I have done the same without any issue. The data are same like above. So what can we do for a single post like above?? – Reactoo Aug 12 '21 at 10:12
  • You possibly couldn't have done the same and not have gotten an error if the data is an `object` instead of an `array`. – Sinan Yaman Aug 12 '21 at 10:16
0

if you don't have any error from the catch, it means you're making a good request to the server, but you need to display loader in for the time out

if (!food?.length) return <div>Loading </div>    
return (
      <div>
        <div className="food-page">         
             {food?.map((foodItem) => {
                return <PageHeader  {...foodItem} key={foodItem.id} />;
              })}
               <Customize />
              {food?.map((foodItem) => {
                return <FoodDescription  {...foodItem} key={foodItem.id} />;
              })}       
        </div>
      </div>
      );
    }
Mohamed Ahmed
  • 259
  • 3
  • 17
  • The error message doesn't imply that `food` is null or undefined. It says `map` is not a function, pointing out that `food` is not an instance of Array – Sinan Yaman Aug 12 '21 at 10:15
0

You are calling an endpoint that return one item not a list of foods , I guess it is like "GetById" , this is an object (one food):

{
    "id": 1,
    "category": "main courses",
    "image": "imgUrl",
    "image_url": "imgUrl",
    "food_name": "butter chicken",
    "subtitle": null,
    "long_title": null,
    "description": "<p>this is a test data from backend for butter chicken in main courses.</p>",
    "price": 49.0,
    "rating": 3.0
}
This code will work but you should keep your code and change the endpoint to (if exist ) "https://texas-crm1.herokuapp.com/api/menus/

useEffect(() => {
    axios.get(`https://texas-crm1.herokuapp.com/api/menus/${id}`)
    .then(abc=>{
      console.log(abc.data)
let arr=[abc.data]
      setFood(prev=>arr)
    })
    .catch(err =>{
      console.log(err) 
    })
  }, [])

"

Alwani Anis
  • 260
  • 3
  • 11