如何等待来自 API 的数据作为组件中的道具?
How to await data coming from an API as a prop in a component?
一旦我的数据从 API 加载,我将尝试在组件上发送一个 prop。但是,即使我使用 async await 来等待我的数据,我仍然收到以下错误: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.
我的过程:
- 有两个设置状态:1) updateLoading 和 2) setRecordGames
- 加载数据后,我会将 updateLoading 设置为 false,然后使用 API.
中的数据设置 recordGames
我的问题:
似乎当我在组件中传递数据时,React 没有等待我的数据加载并给我一个错误。
这是我的代码:
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
我会为数据创建一个钩子,并在获取时为它设置数据,
您可以使用扩展运算符克隆数据并将其传递。
或更好 return 该组件仅当数据中有内容时
{
data && <CustomPieChart data={recordGames} />
}
最好使用您的加载挂钩制作一些加载程序 (gif/svg),以便在仍在获取数据时显示它。
一旦我的数据从 API 加载,我将尝试在组件上发送一个 prop。但是,即使我使用 async await 来等待我的数据,我仍然收到以下错误: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.
我的过程:
- 有两个设置状态:1) updateLoading 和 2) setRecordGames
- 加载数据后,我会将 updateLoading 设置为 false,然后使用 API. 中的数据设置 recordGames
我的问题: 似乎当我在组件中传递数据时,React 没有等待我的数据加载并给我一个错误。
这是我的代码:
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
我会为数据创建一个钩子,并在获取时为它设置数据, 您可以使用扩展运算符克隆数据并将其传递。 或更好 return 该组件仅当数据中有内容时
{
data && <CustomPieChart data={recordGames} />
}
最好使用您的加载挂钩制作一些加载程序 (gif/svg),以便在仍在获取数据时显示它。