0

I'm attempting to ping an API, then map that data to a page. The JSON data looks like this (we don't have any control over this):

{
    "count": 1,
    "results": [
        {
            "legends_total": {
                "series": "Legends Total",
                "stubs_needed": 346556,
                "total_cost": 1224043,
                "cards_owned": 282,
                "cards_required": 352,
                "collection_excluded": "Faces of the Franchise"
            },
            "cover_athletes": {
                "series": "Cover Athletes",
                "stubs_needed": 0,
                "series_cost": 101798,
                "cards_owned": 12,
                "cards_required": 12
            },
            "second_half": {
                "series": "2nd Half",
                "stubs_needed": 53257,
                "series_cost": 96962,
                "cards_owned": 11,
                "cards_required": 22
            },
        }
    ]
}

So what I'm trying to output is simply:

Name: <series>
Cards Owned: <cards_owned>

Here is what I have tried (simplified a bit):

const BrettCollection = props => {
  const [brettDataIsLoading, setBrettDataIsLoading] = useState(false)
  const [inventoryBrettData, setInventoryBrettData] = useState([])

  const fetchData = useCallback(async () => {
    setBrettDataIsLoading(true)
    axios
      .get(
        `https://api.showzone.io/api/user-inventory/${props.currentUser?.uid}/legends-collection/`
      )
      .then(async getUserInventoryLegendData => {
        if (getUserInventoryLegendData.data) {
          setInventoryBrettData(getUserInventoryLegendData.data.results[0])
          setBrettDataIsLoading(false)
        } else {
          setBrettDataIsLoading(false)
        }
      })
      .catch(err => {
        setBrettDataIsLoading(false)
      })
  }, [props.currentUser?.uid])

  useEffect(fetchData, [fetchData])

  const SeriesData = () => {
    Object.keys(inventoryBrettData)?.map((series, data) => {
      return (
        <>
          <h1>Series: {data.series}</h1>
          <p>Cards Owned: {data.cards_owned}</p>
        </>
      )
    })
  }

  return (
    <>
      {!brettDataIsLoading ? (
        <Card mb={6}>
          <CardContent>
            <Typography variant="h4" gutterBottom>
              Brett Collection
            </Typography>
            <Grid container spacing={6}>
              <Grid item xs={12} md={6}>
                <SeriesData />
              </Grid>
            </Grid>
          </CardContent>
        </Card>
      ) : (
        <>
          <LoaderBaseballInline></LoaderBaseballInline>
        </>
      )}
    </>
  )
}

However, I get the following error:

Error: SeriesData(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

How can I map over the nested JSON and to create the component in this way?

JeremyE
  • 1,368
  • 4
  • 20
  • 40
  • You have a path in `SeriesData` that doesn't return anything. It's in the first render then the state is an empty array. – Konrad Jul 30 '22 at 08:53
  • You are also using `Object.keys` which returns only keys and you want the data. You probably meant `Object.entries` or `Object.values`. Also, second argument of `map`s callback is index, not data – Konrad Jul 30 '22 at 08:55
  • 1
    @KonradLinkowski - I don't think so. If `inventoryBrettData` is `[]`, then is `[]`, and if you `map` that, you get `[]`, not "nothing." It's perfectly fine to return `[]` from a component. The result is nothing being displayed, not an error. The real problem is that the arrow function is using the non-concise form, but has no `return`. – T.J. Crowder Jul 30 '22 at 08:58

1 Answers1

0

Try this in SeriesData component

edit

  const SeriesData = () => {
    
      return (
        Object.values(inventoryBrettData)?.map(data => 
        (<>
          <h1>Series: {data.series}</h1>
          <p>Cards Owned: {data.cards_owned}</p>
        </>)
      )
    )
  }
voyt97
  • 176
  • 10