Next.js return the 404 error page in getInitialProps
Asked Answered
C

9

32

Currently I am following this example on how to redirect users in getInitialProps

https://github.com/zeit/next.js/wiki/Redirecting-in-%60getInitialProps%60

The problem is, if I want to return 404 like this, it will return a blank page instead of the usual Next.js 404 error page.

context.res.writeHead(404)
context.res.end();

Please note I know using ExpressJs and using statuscode 404 works, however, for this project I am not allowed to use ExpressJs so I need to use typical nodejs writeHead to do it.

Christianly answered 1/12, 2017 at 4:8 Comment(1)
Next.js 10 makes this super simple, find up to date answer belowDisorganize
V
56

Next v10 allows to return 404 page (not with props, but just plain as it is below)

  if (!checkItem) {
    return {
      notFound: true
    }
  }

Full code that works for me: ✅✅✅

export const getServerSideProps = wrapper.getServerSideProps(async ({ req, res, locale, query, store }) => {
  const { productId, categoryId } = query
   
  const checkItem = await getProductBySlugSSR(productId, categoryId, store)

  if (!checkItem) {
    return { // <-----------------does the trick here!!
      notFound: true
    }
  }
    
  return {
    props: {
      ...await serverSideTranslations(locale, ['common']),
    }
  }
})

Documentation: https://nextjs.org/blog/next-10#notfound-support

Valentinavalentine answered 28/4, 2021 at 12:4 Comment(5)
This should be the accepted answer as of 2021. (Next.js v10.2)Haroldharolda
@Haroldharolda no, the OP was asking for getInitialProps, but not found support is only available for getStaticProps and getServerSidePropsStoeber
Where does wrapper come from?Hessian
@Hessian it comes from: import { HYDRATE, createWrapper } from 'next-redux-wrapper' export const wrapper = createWrapper(initStore)Valentinavalentine
This is the true answer for 404 problemCrosswise
Q
25

In order to do that, you’ll have to render the Error page in your page.

You can do something like this:

import React from 'react'
import ErrorPage from 'next/error'

class HomePage extends React.Component {
  static async getInitialProps(context) {
    try {
      const data = await retrieveSomeData()
      return { data }
    } catch (err) {
      // Assuming that `err` has a `status` property with the HTTP status code.
      if (context.res) {
        context.res.writeHead(err.status)
      }
      return { err: { statusCode: err.status } }
    }
  }

  render() {
    const { err, data } = this.props

    if (err) {
      return <ErrorPage statusCode={err.statusCode} />
    }

    /*
     * return <Something data={data} />
     */
  }
}

If you have a custom error page, instead of importing next/error, you’ll have to import your custom _error page.

Quid answered 14/12, 2017 at 17:34 Comment(0)
D
7

Implement your getInitialProps along the lines of:

    static async getInitialProps(context) {
        const {res} = context;

        ...

        if ([something went wrong]) {
            if (res) {
                res.statusCode = 404;
            }

            return {
                err: {
                    statusCode: 404
                },
            };
        }
        ...

Then in render() check if err is defined in state, in which case return the ErrorPage (default or custom one, depending on your implementation) and that's it! The statusCode inside err is just for more granular message on the ErrorPage so it needs to be passed for it as props.

Dorkus answered 16/1, 2019 at 9:20 Comment(0)
P
5

Here's how I do it

import ErrorPage from 'next/error'

const Mycomponenet = () =>{
   if (!exists) {
        return <ErrorPage statusCode={404}/>
      }
}

Piecemeal answered 12/12, 2022 at 16:27 Comment(0)
D
2

As of NextJS 10, you can now include notFound: true in the return object of getStaticProps && getServerSideProps to redirect to the 404 page

Here are the release notes: https://nextjs.org/blog/next-10#redirect-and-notfound-support-for-getstaticprops--getserversideprops

Disorganize answered 14/1, 2021 at 9:59 Comment(0)
T
2

If you are using the new AppRouter, you can use the NotFound() function:

See the NextJS docs: https://nextjs.org/docs/app/api-reference/functions/not-found

import { notFound } from 'next/navigation'
 
async function fetchUser(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}
 
export default async function Profile({ params }) {
  const user = await fetchUser(params.id)
 
  if (!user) {
    notFound()
  }
 
  // ...
}
Text answered 24/7, 2023 at 12:58 Comment(0)
G
1
import App, { Container } from 'next/app'
import React from 'react'
import Head from 'next/head'
import * as Sentry from '@sentry/node'
import Error from './_error'

require('es6-promise').polyfill()
require('isomorphic-fetch')

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}
    let e
    if (Component.getInitialProps) {
      try {
        pageProps = await Component.getInitialProps(ctx)
      } catch (error) {
        e = error
        Sentry.captureException(error) //report to sentry
      }
    }
    return { pageProps, e }
  }

  render() {
    const { Component, pageProps, e } = this.props
    if (e) {
      return <Error /> // customize your error page
    }
    return (
      <Container>
        <Head>
          <title> Your title</title>
        </Head>
        <Component {...pageProps} />
      </Container>
    )
  }
}

export default MyApp

This works like a charm ~ just try catch in next/app, then it works for all the pages

Granular answered 25/1, 2019 at 7:1 Comment(0)
P
1

If you just have to implement the 404 PAGE like you do in cra

the code provided can be helpful: eg.

 import AComponent from '../acomponent';
 import Error from '../error';
  
 const User = (data) => {

   return data.id ? <AComponent /> : <Error />
 }

 User.getInitialProps = async (ctx) => {
   const res = await fetch(...data) // list of items = []
   const data = await res.json()

   return data;
 }
Pommel answered 1/10, 2020 at 7:47 Comment(0)
I
-2

I am using this and it works for me

res.sendStatus(404)
Incinerator answered 26/1, 2022 at 10:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.