使用useSWR获取数据渲染遇map报错,求动态渲染方案
解决useSWR获取数据后map报错及动态渲染任意数据结构的问题
一、报错原因分析
fetchedUsers.map is not a function的核心问题是:你拿到的fetchedUsers不是数组。从你给出的预期接口响应来看,返回的是一个包含name数组和id字段的对象,直接对整个对象调用数组方法map必然报错。
二、先修复当前基础渲染问题
1. 修正渲染逻辑(针对已知接口结构)
先针对你给出的接口返回结构调整渲染代码,同时修复原代码的语法错误:
const { data, error, isLoading } = useSWR(shouldFetch ? "http://localhost:5000/users": null, fetcher); const fetchedUsers = data; // 渲染部分 <Typography> {isLoading ? '加载中...' : error ? '加载失败' : fetchedUsers ? fetchedUsers.name.map((item) => ( <div key={item.id}> ID: {item.id}, 年龄: {item.age} </div> )) : 'Students Portal'} </Typography>
注意:
- 原代码缺少括号
(:fetchedUsers?应改为fetchedUsers ? ( - React列表渲染必须加唯一
key属性,这里用item.id更可靠
2. 补充状态处理
利用useSWR自带的isLoading状态,给用户提供加载中的反馈,避免页面空白。
三、实现适配任意数据结构的动态渲染
要支持任意JSON结构的自动渲染,需要编写一个递归组件,处理对象、数组、基础数据类型等所有情况:
1. 编写通用动态渲染组件
const DynamicRenderer = ({ data }) => { // 处理null/undefined if (data == null) return <span>无数据</span>; // 处理数组类型 if (Array.isArray(data)) { return ( <ul style={{ paddingLeft: '20px', margin: '4px 0' }}> {data.map((item, index) => ( <li key={item.id || index}> <DynamicRenderer data={item} /> </li> ))} </ul> ); } // 处理对象类型 if (typeof data === 'object') { return ( <div style={{ paddingLeft: '20px', margin: '4px 0' }}> {Object.entries(data).map(([key, value]) => ( <div key={key} style={{ margin: '2px 0' }}> <strong>{key}:</strong> <DynamicRenderer data={value} /> </div> ))} </div> ); } // 处理字符串、数字、布尔值等基础类型 return <span style={{ marginLeft: '8px' }}>{String(data)}</span>; };
2. 使用组件渲染任意数据
把原来的渲染代码替换成以下内容,不管接口返回什么嵌套结构,都能自动解析渲染:
<Typography> {isLoading ? '加载中...' : error ? '加载失败' : fetchedUsers ? <DynamicRenderer data={fetchedUsers} /> : 'Students Portal'} </Typography>
四、额外注意事项
- 确保接口返回合法JSON格式,如果接口可能返回非JSON数据,在
fetcher里增加容错处理:const fetcher = (url) => axios.get(url) .then((res) => { if (typeof res.data !== 'object') throw new Error('返回数据格式错误'); return res.data; }); - 递归组件的
key优先使用数据自身的唯一标识(如item.id),无唯一标识时再用index - 可以根据需求给
DynamicRenderer添加样式,比如不同数据类型用不同颜色,让层级更清晰
内容的提问来源于stack exchange,提问作者Tini
相关产品推荐
相关产品推荐

