1

I am trying to map an array of objects within an object and I can't seem to get it working. My code's goal is to map and then display the content within the "menu" array.

Here is the structure of the object (logged to console from a state).

Object {
  "id": 1,
  "img": "https://cuisinederue.org/wp-content/uploads/2019/08/Greg2.png",
  "menu": Array [
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Greg's Burger",
      "price": 1,
    },
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Poutine double cheese bacon",
      "price": 1,
    },
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Cône de poulet pop corn et frites maison",
      "price": 1,
    },
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Grilled cheese Philly steak",
      "price": 1,
    },
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Poutine Philly cheese steak",
      "price": 1,
    },
    Object {
      "description": "Les prix sont défini à la tête du client",
      "name": "Boulette de mac'n'cheese",
      "price": 1,
    },
  ],
  "name": "Greg's dinner",
  "type": "SOUTHERN COMFORT",
} 

And here is the code that I'm trying to get to work: (specifically the details.menu.map part)


const Details = ({navigation, idTruck}) =>{
  const [details, setDetails] = useState([]);
  const [detailsDone, setDetailsDone] = useState(false);

  const getDetails = () => {  
    fetch("https://foodtrack-420kbc-lg.herokuapp.com/trucks/1").then(res => res.json()).then(resp => setDetails(resp));
  }

  if(!detailsDone)
  {
    getDetails();
    setDetailsDone(true);
  }
  console.log(details);
  return (
    <View style={styles.container}>
      <Header title='Details'></Header>
      <Image name="logo" style={styles.detailsImage} source={{uri: details.img}}></Image>
      <Text name="nom">{details.name}</Text>
      <Text name="style">{details.type}</Text>


        {


          details.menu.map(({description, name, price}) => 
            <View style={styles.container}>
              <Text name="nom">{name}</Text>
              <Text name="prix">{price}</Text>
              <Text name="desc">{description}</Text>
            </View>
          )
        }

    </View>
  )
} 

The error I am getting is: TypeError: undefined is not an object (evaluating 'details.menu.map'

Any help is greatly appreciated!

6
  • Change like this details.menu.map((detail) => and <Text name="nom">{detail.name}</Text> Commented May 30, 2020 at 22:50
  • @sibabratswain sadly I still get the same error. Thanks for the suggestion though! Commented May 30, 2020 at 22:53
  • Did you change for price and description like name right? Commented May 30, 2020 at 22:55
  • @sibabratswain yes, I'm still getting TypeError: undefined is not an object (evaluating 'details.menu.map' Commented May 30, 2020 at 22:58
  • Check with this one stackoverflow.com/a/45857744/9739044 Commented May 30, 2020 at 23:01

2 Answers 2

1
  1. You have big problem in controlling JS asynchronous. Please try to understand it first before you start to study reactJS. Some async functions: setTimeout, setInterval, Ajax (call api), here is small tut . From this point, you don't need to use detailsDone state.
  2. High performance when use useEffect for calling api only 1 time.
const initValue = {
    id: 0,
    name: "",
    type: "",
    img: "",
    menu: []
}
const [details, setDetails] = useState(initValue); // init value is object, not array

React.useEffect(() => {
    fetch("https://foodtrack-420kbc-lg.herokuapp.com/trucks/1")
        .then(res => res.json())
        .then(resp => setDetails(resp));
}, []); // ensure call api run 1 time when this component render.
Sign up to request clarification or add additional context in comments.

1 Comment

You're right that my code isn't optimized however this didn't solve my problem sadly. Thanks for the tips and I will look into better learning async JS!
1

it looks like you're trying to map over details.menu, but when the component loads initially, details is an empty array, which does not have property menu.

One workaround would be to conditionally render something else (like a loading indicator) until the data is set into component state.

1 Comment

Thank you, I ended up using a combination of this and the top answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.