I'm using useSWR hook in components. Under api folder I have api. I'm using app router
.
Components are imported in page.
Problem is that if API encounters some error then how should I return it to the components which are using useSWR hook.
Components rely on {isLoading,error,data,mutate}
destructured from useSWR hook
to show various states.
So how should I return error so that useSWR hook's error state gets set.
I don't want to pass data :{error : ...} as it causes useSWR hook's data state to be set which creates rendering problems.
On error my component also allows user to Retry by calling mutate
NextJS Version: 13.5.4
Folder Structure :
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
route.js under app\api\tryapi\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
}
}
Try Component under 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
Output:
- After passing wrong url & returning
return error
in api route.
Terminal shows :
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
- If return I response
return NextResponse.json({ data: { error: true } })
Then Retry functionality gets broken.
Shows Error in Page:
data.map is not a function
TypeError: data.map is not a function
On Browser Console : Data gets set as below if user clicks on Retry :
SyntheticBaseEvent {_reactName: 'onClick', _targetInst: null, type: 'click', nativeEvent: PointerEvent, target: button, …}
After Reading this i understood how to handle & send error :
Regarding the error:
I changed
to
route.js :
I also added axios in route.js instead of fetch, axios directly enters catch when status is in 400s.
(Yes URL is wrong to purposely get an error msg, from API)
Under
catch statement
I added & also changedcatch(error)
tocatch(e)
(to prevent confusion):After doing this error state of useSWR was getting set, Error State from useSWR hook returned (expected behaviour achieved) :
Explaination : Next.js extends Request and Response Web APIs