如何在使用useSWR钩子时处理NextJS 13 API Routes中的错误?

lx0bsm1f  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(78)

我在组件中使用useSWR钩子。在API文件夹下我有API。我使用app router。组件在页面中导入。
问题是,如果API遇到一些错误,那么我应该如何将其返回到使用useSWR钩子的组件。
组件依赖于从useSWR hook解构的{isLoading,error,data,mutate}来显示各种状态。

那么我应该如何返回error,以使useSWR hook的error状态被设置。

  • 我不想传递data:{error:...},因为它会导致useSWR hook的数据状态被设置,从而导致渲染问题。*

在错误时,我的组件还允许用户通过调用mutate来重新配置

NextJS版本13.5.4
文件夹结构:

projectName
├── .gitignore
├── app
│   ├── api
│   │   └── tryapi
│   │       └── route.js
│   ├── components
│   │   └── Try
│   │       └── Try.js
│   ├── error.js
│   ├── favicon.ico
│   ├── globals.css
│   ├── layout.js
│   ├── not-found.js
│   ├── page.js
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── README.md
└── tailwind.config.js

字符串
app\api\tryapi\route.js下的route.js

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')
        // TO SIMULATE A ERROR IM PASSING WRONG URL 

        let UserData = await data.json()
        // console.log(UserData.users);

        return NextResponse.json({ data: UserData.users })
    } catch (error) {

        // return NextResponse.json({ data: { error: true } })

        return error
        // THIS THROWS ERROR WHICH IS PROPERLY HANDLED BY useSWR hook in component

    }

}

尝试app\components\Try\Try.js下的组件

'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)

const Try = () => {

    const { isLoading, error, data, mutate } = useSWR('/api/tryapi', Fetcher)

    if (isLoading) return "Loading...";

    else if (error) return <div>
        {error.toString()}
        <br />
        <button onClick={mutate}>Retry</button>

    </div>

    else {
        console.log(data);
        return (
            <div>
                {

                    data.map((v, i) => (
                        <p>{v.firstName}</p>
                    ))
                }
            </div>
        )
    }

}

export default Try

输出:

  • 在API路由中传递错误URL并返回return error后。

终端显示:

Error: No response is returned from route handler 'D:.....\app\api\tryapi\route.js'. Ensure you return a `Response` or a `NextResponse` in all branches of your handler

  • 如果返回I response return NextResponse.json({ data: { error: true } }),则会中断故障恢复功能。

页面显示错误:

data.map is not a function
TypeError: data.map is not a function

**在浏览器控制台:**用户点击按钮,数据设置如下:

SyntheticBaseEvent {_reactName: 'onClick', _targetInst: null, type: 'click', nativeEvent: PointerEvent, target: button, …}

8ehkhllq

8ehkhllq1#

SyntheticBaseEvent {_reactName: 'onClick',.....

字符串
我变了

<button onClick={mutate}>Retry</button>


<button onClick={() => { mutate() }}>Retry</button>

route.js:

我还在route.js中添加了axios,而不是fetch,axios在状态为400时直接进入catch。

let data = await axios.get('https://dummyjson.com/users/1d1ouhl1')

  • (是的URL是错误的,故意从API获取错误消息)*

catch statement下,我添加并将catch(error)更改为catch(e)(以防止混淆):

return NextResponse.json("", {
            status: e.response.status || 500,
            statusText: e.response.code || "Internal Server Error"
        })


执行此操作后,useSWR的错误状态已设置,useSWR钩子返回错误状态(实现预期行为):

code: "ERR_BAD_RESPONSE"
message: "Request failed with status code 500"
name: "AxiosError"
response : 
   status: 500
   statusText: "Internal Server Error"
   data: ""
.....

**说明:**Next.js扩展了请求和响应Web API

Response.json(data, options)

  • body,选项都是可选的
  • 在发送错误时,我将主体部分保持为空,由于错误对象中接收的数据为“”空,因此仅设置状态。(我更喜欢保持为空,因为它没有使用)

相关问题