skip to Main Content

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 (
        //
    )
}

3

Answers


  1. 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 (
            //
           )
        }
    
        
    
    Login or Signup to reply.
  2. 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
              )}
        </>
    )
    
    Login or Signup to reply.
  3. 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.

    1. Create a component i.e. ErrorComponent.jsx
    export default function ErrorComponent() {
      return (
        <div>
          Im lost 404
        </div>
      )
    }
    
    1. Create a page inside the page directory, name it 404.jsx
    import ErrorComponent from 'your-error-component-location';
    
    const Error404Page = () => <ErrorComponent />;
    
    export default Error404Page;
    
    
    1. Modify your code to
    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
        );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search