useSWR加载/验证阶段返回数据规则及中间数据异常问询
useSWR返回数据规则及问题分析
核心结论
- useSWR不会返回fetcher回调中多步
then的中间数据,它只会接收fetcher最终resolve的结果作为data的值。 - useSWR保证返回的
data仅可能是以下几种情况:undefined:初始加载阶段、请求未完成时、fetcher抛出错误(Promise被reject)时- 缓存的历史成功响应数据:如果之前请求成功过,会优先返回缓存数据,再进行后台重新验证
- 配置的fallback数据:若通过
fallback选项预设了初始数据,加载初期会返回对应值 - fetcher最终resolve的结果:即你代码中第二个
then返回的data.content(Foo[]类型)
你遇到的问题原因
你看到的idpData为响应JSON对象(而非预期的Foo[])的情况,并非useSWR返回了中间数据,而是你的fetcher逻辑或API响应存在异常:
- 你的fetcher未处理HTTP错误状态码(如401、500等):当请求返回非200状态码时,
fetch不会自动抛出错误,仍会执行res.json(),若此时API返回的错误JSON对象没有content字段,第二个then中data.content会是undefined;如果API在某些场景下直接返回了未经过content包裹的原始对象(而非分页结构),也会导致fetcher返回非预期值。 - 类型定义与实际响应不匹配:你给fetcher标注了返回
Promise<Foo[]>,但实际运行中API可能返回不符合结构的数据,导致类型校验失效,出现非预期的data格式。
修复方案
- 完善fetcher的错误处理:检查响应状态码和数据结构,主动抛出异常避免无效数据流入:
const { data: idpData } = useSWR<Foo[]>( buildUrl(() => `/[...]/idps`), async (url: string): Promise<Foo[]> => { const res = await fetch(url, { headers: { Authorization: `Bearer ${accessToken}` } }); if (!res.ok) { throw new Error(`请求失败,状态码:${res.status}`); } const data = await res.json() as PaginationWithContentDetails; if (!Array.isArray(data.content)) { throw new Error("响应结构无效:缺少或非数组类型的'content'字段"); } return data.content; } );
- 增强渲染时的防护逻辑:通过类型校验避免意外数据导致报错:
{Array.isArray(idpData) ? idpData.map((idp: Foo) => ( <option key={idp.id} value={idp.id} disabled={!hasEmailValid}> {idp.name} </option> )) : null}
内容的提问来源于stack exchange,提问作者Thorsten Schöning
相关产品推荐
相关产品推荐

