Redirect to 404 when custom [slug] is not found in Next JS
Asked Answered
M

5

7

I'm surprised I can't find this anyway but here is my issue. I have a Next JS site with the path /location/[location].js The page looks pretty basic

import { nodes } from '../../components/data/nodes'

export default function Location() {
    const router = useRouter()

    useEffect(() => {
         //Do various things   
    }, [])
   
    return (
        <Layout>
             ...My website...
        </Layout>
    )
}

and nodes looks like this

export const nodes = [
{
    id: 'Test1'
}, {
    id: 'Test2'
}, {
    id: 'Test3'
}]

So how can I say if my [location] slug does not match any node id's go to the 404 page? I tried some janky garbage that just feels wrong and throws console errors:

var counter = 1
  for (var node of nodes) {
    if (router.query.location == node.id) {
      break
    } else if (counter++ >= nodes.length) {
      return <Error statusCode={404} />
    }
  }

Can someone help me work this out. Thanks

Malissa answered 17/3, 2022 at 5:34 Comment(0)
S
5

I'd prefer you to use getStaticProps & getStaticPaths In order to solve this problem. You can use the getStaticProps to fetch the static props. and to define what paths are valid you can use getStaticPaths and load the paths from your nodes variable. If the path doesn't exist you can then simply return a 404 error instead of props

Please refer the official document of Next.js to know more about the getStaticProps & getStaticPaths

Schoolbook answered 17/3, 2022 at 7:15 Comment(0)
N
2

For nextjs 13,

You can use function notfound()

Refer here
https://nextjs.org/docs/app/api-reference/functions/not-found

In your case, when the location is not found in the nodes array, simply call function

notFound()

var counter = 1
  for (var node of nodes) {
    if (router.query.location == node.id) {
      break
    } else if (counter++ >= nodes.length) {
      notFound()
    }
  }
Nanice answered 30/7, 2023 at 16:15 Comment(0)
V
1

You can easily define a state and according to state render your component.

import Error from "next/error";

// inside functional component
 const [errorCode , setErrorCode] = useState(0);
 const router = useRouter():
 
 useEffect(() => {
  const location =  router.query.location
  const search = nodes.filter(item => item.id === location ):
  if(search.length === 0){
    setErrorCode(404)
  }
 },[])
 
 if (errorCode == 404) {
   return (
      <Error statusCode={errorCode} title="page Not Found" />
   </>
   );
}
return (
  <Layout>
         ...My website...
    </Layout>
)
Veolaver answered 17/3, 2022 at 6:58 Comment(0)
A
1

Okay so there are lots of reasons why you would want to use ssr over ssg, especially when building an ecommerce store or something similar, while using getStaticPaths will solve the issue, if you want a solution for getServerSideProps, this is my solution:

If you know how the data is formated, in this case the product has a title, then you can use this to set up an error in the returned props.

export async function getServerSideProps({ params }) {
    const slug = params.slug;

    const res = await fetch(`https://someAPI`);
    const product = await res.json();

    return {
        props: {
            params,
            product,
            slug,
            error: !recipe.title 
        }
    }
}

Then somewhere in the component:

function YourComponent({ product, slug, error }) {

    // If there is no product matching the slug
    const router = useRouter();
    if(error) {
        useEffect(() => {
            router.push('/404');
        }, [])
        return
    }

    return (
        //some JSX
    )
Arianism answered 29/3, 2023 at 11:37 Comment(1)
You can't use a hook (like useEffect) in a control structure (like if). Using the router.push without the useEffect should work better.Carabineer
E
0

You can redirect to the 404.tsx not found page defined in your pages directory by setting the fallback returned value to false in getStaticPaths.

export const getStaticPaths : GetStaticPaths = async () => {
  ... 
  // { fallback: false } means other routes should 404
  return { paths, fallback: false }
}

Now If a slug or location is wrong and doesn't match any of the returned paths, It will redirect to the error page.

Emanuelemanuela answered 26/7 at 10:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.