Reputation: 4055
I have a dynamic route in my NextJS app /team/[id]
.... When the page loads it goes off to the API and checks the ID of the team and then returns the information, if the ID doesn't exist on the API, it returns a 404. Is there any way to to show a 404 if the data returned back from the API is also a 404? .. At the moment, i have a page loader which runs when loading, but when the ID doesn't exist, the pageloader just keeps going and doesn't stop.
This is what I currently have which works fine for ID's which exist, but breaks if an id doesnt exist;
import useSWR from "swr"
import axios from '@/lib/axios'
import { useRouter } from 'next/router'
const ViewTeam = () => {
const router = useRouter()
const { id } = router.query
const { data: team, error, mutate } = useSWR('/api/team/' + id, () =>
axios.get('/api/team/' + id)
.then(response => response.data.data)
)
if (! team) {
return (<PageLoader />)
}
return (
//
)
}
Upvotes: 0
Views: 2191
Reputation: 459
If you dont want your url to be changed when team
is not found but want to show same 404 page, then you can do something like this.
export default function ErrorComponent() {
return (
<div>
Im lost 404
</div>
)
}
import ErrorComponent from 'your-error-component-location';
const Error404Page = () => <ErrorComponent />;
export default Error404Page;
import ErrorComponent from 'your-error-component-location';
const { data: team, error, isLoading, mutate } = useSWR('/api/team/' + id, () =>
axios.get('/api/team/' + id).then(response => response.data.data)
)
if (!team && isLoading) {
return (<PageLoader />)
}
// this is responsible to show your desired 404 component, it might be a
// case that your api is returning an error, so worth checking the error too
if(!team || !!error) {
return <ErrorComponent/>
}
return (
// render your team jsx
);
Upvotes: 0
Reputation: 81
You should ideally fetch data inside useEffect. By using useEffect with proper dependency management, you ensure that data fetching and any associated cleanup happen at the appropriate times, leading to a more predictable and efficient React application.
const [done, setDone] = useState(undefined);
useEffect( () => {axios.get('/api/team/' + id)
.then(response => response.data.data)
.then(()=> setDone(true)
},[])
using [ ] ensures you will only fetch once on mount.
Inside return() you should check if fetching was completed if not show loading page
return(
<>
{!done ? (
<PageLoader/>
) : (
//whatever you wanna show
)}
</>
)
Upvotes: -2
Reputation: 61
Usually you should have something like isLoading
or loading
state which will show your <PageLoader />
component. In useSWR
docs I see it is isLoading
. So you just do:
if(isLoading){
return <PageLoader />
}
and after that depending on your request response you define what should happen when it gets the data (correct or wrong). If it's wrong it should be for example:
if(!team){
router.push("/404");
}
and when it's correct you just show rest:
return (
///
)
so finally it should look something like:
const { data: team, error, mutate, isLoading } = useSWR('/api/team/' + id, () =>
axios.get('/api/team/' + id)
.then(response => response.data.data)
)
if (isLoading) {
return (<PageLoader />)
}
if(!team){
router.push("/404");
} else {
return (
//
)
}
Upvotes: 1