I am trying to send a prop on a component once my data loads from an API. However, even though I am using async await to await from my data, I am still getting an error of: Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
My process:
My Problem: It seems that when I pass data in the component, React does not wait for my data load and gives me an error.
This is my code:
import useLoadRecords from '../../hooks/useLoadRecords'
import { CustomPieChart } from '../charts/CustomPieChart'
export const GameDistribution = () => {
const { records, loading } = useLoadRecords()
let data = records
console.log(data) // This logs out the records array
return (
<div>
// once loading is false, render these components
{!loading ? (
<>
<div>
{recordGames.length > 0 ? (
// This line seem to run as soon as the page loads and I think this is the issue. recordGames is empty at first, but will populate itself when the data loads
records.length > 0 && <CustomPieChart data={data} />
) : (
<div>
No games
</div>
)}
</div>
</>
) : (
<span>Loading...</span>
)}
</div>
)
}
// useLoadRecords.js
import { useState, useEffect } from 'react'
import { API } from 'aws-amplify'
import { listRecordGames } from '../graphql/queries'
// Centralizes modal control
const useLoadRecords = () => {
const [loading, setLoading] = useState(false)
const [records, updateRecords] = useState([])
useEffect(() => {
fetchGames()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const fetchGames = async () => {
try {
let recordData = await API.graphql({
query: listRecordGames,
})
setLoading(false)
let records = recordData.data.listRecordGames.items.map(
(item) => item.name
)
let result = Object.values(
records.reduce((acc, el) => {
if (!acc[el]) acc[el] = { name: el, plays: 0 }
acc[el].plays++
return acc
}, {})
)
updateRecords(result)
} catch (err) {
console.error(err)
}
}
return { records, loading }
}
export default useLoadRecords
I would make a hook for the data and setData to it when fetching , you can clone the data using spread operator and this pass it. or better return that component only if there is something in data for example
{
data && <CustomPieChart data={recordGames} />
}
and it would be nice to make a some loader (gif/svg) using your loading hook so it can be shown when the data is still being fetched.