React嵌套JSON映射组件报错:render未返回内容问题排查
问题分析与修复方案
需求与报错
需要调用API获取嵌套JSON数据,展示每个series的名称和已拥有卡牌数(cards_owned),但代码运行时报错:
Error: SeriesData(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
原始JSON结构
{"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}}]}
出错的原始代码
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> </> )} </> ) }
修复步骤与修正后代码
核心问题点
- SeriesData组件未返回渲染结果:组件内的
map函数执行后没有被返回,导致组件无输出。 - map参数使用错误:
Object.keys()返回的是对象键名数组,map的第一个参数是键名,第二个是索引,不是数据对象,需通过键名从inventoryBrettData中获取对应数据。 - 初始状态类型不匹配:
inventoryBrettData初始值设为数组[],但API返回的是对象,应改为{}避免遍历异常。 - 缺少列表key属性:React列表渲染需给每个元素添加唯一
key,消除控制台警告。
修正后完整代码
import React, { useState, useCallback, useEffect } from 'react'; import { Card, CardContent, Typography, Grid } from '@mui/material'; import axios from 'axios'; import LoaderBaseballInline from './LoaderBaseballInline'; // 假设组件路径正确 const BrettCollection = props => { const [brettDataIsLoading, setBrettDataIsLoading] = useState(false); // 初始值改为空对象,匹配API返回的数据类型 const [inventoryBrettData, setInventoryBrettData] = useState({}); const fetchData = useCallback(async () => { setBrettDataIsLoading(true); try { const getUserInventoryLegendData = await axios.get( `https://api.showzone.io/api/user-inventory/${props.currentUser?.uid}/legends-collection/` ); if (getUserInventoryLegendData.data) { setInventoryBrettData(getUserInventoryLegendData.data.results[0]); } } catch (err) { console.error('获取数据失败:', err); } finally { setBrettDataIsLoading(false); } }, [props.currentUser?.uid]); useEffect(fetchData, [fetchData]); const SeriesData = () => { // 用Object.entries直接获取键值对,更直观;同时添加return返回渲染结果 return Object.entries(inventoryBrettData).map(([key, data]) => ( <div key={key}> {/* 添加唯一key */} <h1>Series: {data.series}</h1> <p>Cards Owned: {data.cards_owned}</p> </div> )); }; 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 /> )} </> ); }; export default BrettCollection;
内容的提问来源于stack exchange,提问作者JeremyE
相关产品推荐
相关产品推荐

