NextJS 13 App Router中API Routes结合useSWR的错误处理
解决方案
1. 修改API路由(route.js)
在catch块返回带错误状态码的响应,让axios识别为请求错误,避免错误数据流入useSWR的data:
import { NextResponse } from 'next/server' export async function GET() { try { console.log("tryapi !", new Date().toLocaleTimeString()) let data = await fetch('https://dummyjson.com/users') // let data = await fetch('https://dummyjson.com/user12d1d') // 模拟错误 if (!data.ok) { // 处理上游API返回的错误状态码 throw new Error(`上游API错误: ${data.status}`) } let UserData = await data.json() return NextResponse.json({ data: UserData.users }) } catch (error) { // 返回500状态码+错误信息,明确告知客户端请求失败 return NextResponse.json( { message: error.message }, { status: 500 } ) } }
2. 调整Fetcher函数
确保axios遇到非200响应时抛出错误,让useSWR能正确捕获error状态:
const Fetcher = url => axios.get(url) .then(resp => resp.data.data) .catch(err => { // 抛出错误,useSWR会将其赋值给error变量 throw new Error(err.response?.data?.message || '请求失败') })
3. 组件逻辑优化(Try.js)
保留原分支判断的同时,给data.map加上可选链,进一步避免渲染报错:
'use client' import axios from 'axios' import React from 'react' import useSWR from 'swr' const Fetcher = url => axios.get(url) .then(resp => resp.data.data) .catch(err => { throw new Error(err.response?.data?.message || '请求失败') }) const Try = () => { const { isLoading, error, data, mutate } = useSWR('/api/tryapi', Fetcher) if (isLoading) return "Loading..."; if (error) return ( <div> {error.toString()} <br /> <button onClick={() => mutate()}>Retry</button> </div> ) // 仅当data存在时执行map,彻底避免无数据时的报错 return ( <div> {data?.map((v, i) => (<p key={i}>{v.firstName}</p>))} </div> ) } export default Try
方案原理
- API返回非200状态码时,axios会触发catch分支,fetcher抛出的错误会被useSWR捕获并赋值给
error变量,data保持为undefined或缓存值 - 组件分支判断会优先进入
error分支展示错误和重试按钮,不会走到data.map的逻辑 mutate()依然能触发重新请求,重试功能完全正常
内容的提问来源于stack exchange,提问作者Beast80K
相关产品推荐
相关产品推荐

