Search code examples
javascriptreactjsobjectfetch-api

Why will my fetch API call map one nested objects, but not the other?


I'm parsing data from the NASA API using React, and for some reason I can map one nested object within the return but not the other.

Here is my parent component:

import React, { useState } from 'react'
import './NasaAPI.scss'
import NasaImages from './NasaImages'

const NasaAPI = () => {
    const [nasaData, setNasaData] = useState([])
    const [nasaImage, setNasaImage] = useState("")
    const [searchInput, setSearchInput] = useState("")
    const [loading, setLoading] = useState(true)

    const fetchData = async (e) => {
        const data = await fetch(`https://images-api.nasa.gov/search?q=${searchInput}`)
        .then(response => response.json())
        .then(data => setNasaData(data.collection.items))
        .catch(err => console.log(err))
        .finally(setLoading(false))
    }

    const handleSubmit = (e) => {
        e.preventDefault()
        fetchData()
    }

    const handleChange = (e) => {
        setSearchInput(e.target.value)
    }

    return (
        <div>
            <h2>Search NASA Images</h2>
            <form onSubmit={handleSubmit}>
                <input name="searchValue" type="text" value={searchInput} onChange={handleChange}></input>
                <button value="Submit">Submit</button>
            </form>
            <section>
                <NasaImages nasaData={nasaData} loading={loading}/>
            </section>
        </div>
    )
}

export default NasaAPI

Here's where the issue is, in the child component:

import React from 'react'

const NasaImages = ({ nasaData }) => {
    console.log(nasaData)

    return (
        <div>
            <h2>This is a where the data go. 👇</h2>
            {
                nasaData && nasaData.map((data, idx) => {
                    return (
                        <div key={idx}>
                            <p>{data.href}</p>
                            <div>
                                {/* {data.links.map((data) => {
                                    return <p>{data.href}</p>
                                })} */}
                                {data.data.map((data) => {
                                    return <p>{data.description}</p>
                                })}
                            </div>
                        </div>
                    )
                })
            }
        </div>
    )
}

export default NasaImages

The current configuration works, and will display a data.description (data.data.map) mapping property. However, I want the commented code immediately above it to work which displays a data.href (data.links.map) property.

The JSON looks as follows:

some code

So, the issue is that I can map one set of properties, data.data.map, but cannot access the other in the same object, data.links.map, without getting the error:


Solution

  • There exists a data element sans a links property, in other words there is some undefined data.links property and you can't map that. Use Optional Chaining operator on data.links when mapping, i.e. data.links?.map. Use this on any potentially undefined nested properties.

    const NasaImages = ({ nasaData = [] }) => {
      return (
        <div>
          <h2>This is a where the data go. 👇</h2>
          {nasaData.map((data, idx) => (
            <div key={idx}>
              <p>{data.href}</p>
              <div>
                {data.links?.map((data, i) => <p key={i}>{data.href}</p>)}
                {data.data?.map((data, i) => <p key={i}>{data.description}</p>)}
              </div>
            </div>
          ))}
        </div>
      )
    }