Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With NextJS and next-routes, How to Handle 404 from server.js and also client side

I'm wanting my next-routes to gracefully handle file not found (really route not found) when running from server.js (server side) as well as running on the link side with Link. I've got a solution but it's very bulkly and feels like I'm not doing it the best way I could.

I'm pasting below my pages file (pages/speakerdetail.js) that does handle both server and client correctly but it seems wrong to have to have a custom render method in every file that says "Not Found".

I've also got this running as in example in the repo

https://github.com/pkellner/next-routes-problem

import React, {Component} from 'react';
import {Link} from '../routes'
import Router from 'next/router'

class speakerdetail extends Component {

    static async getInitialProps({req,res,query}) {

        console.log("getInitialProps speakerdetail");
        let statusCode = 200;
        let slugSpeaker = '';
        let ccYear = '';
        if (query && query.slugSpeaker) {
            console.log("query.slugSpeaker:" + query.slugSpeaker);
            slugSpeaker = query.slugSpeaker;
        }
        if (query && query.ccYear) {
            console.log("query.ccYear:" + query.ccYear);
            ccYear = query.ccYear;
        }
        if (slugSpeaker != 'douglas-crockford-1124' || ccYear != '2018') {
            if (req) {
                console.log("getInitialProps - res.redirect cause server");
                statusCode = 404;
                res.statusCode = 404;
            } else {
                console.log("getInitialProps - router.push cause client")
                Router.push('/error404');
            }
        }
        return {
            slugSpeaker,
            ccYear,
            statusCode
        };
    }

    render() {

        if (this.props.statusCode == 404) {
            return (
                <div>Not Found</div>
            )
        }

        return (
            <div>
                <b>speakerdetail    {this.props.ccYear}   {this.props.slugSpeaker}   {this.props.statusCode}</b>
                <hr/>
                <Link route='/' >
                    <a>home</a>
                </Link>
            </div>
        );
    }
}

speakerdetail.propTypes = {};
speakerdetail.defaultProps = {};

export default speakerdetail;
like image 558
Peter Kellner Avatar asked Nov 08 '22 01:11

Peter Kellner


1 Answers

Instead of manually checking every params passed to the page, it is better to control from your server.js file:

const next = require('next');
const routes = require('./routes');
const app = next({dev: process.env.NODE_ENV !== 'production'});
const handler = routes.getRequestHandler(app);

// With express
const express = require('express');
app.prepare().then(() => {
    const srv = express();

    srv.get('/:year/:slugSpeaker', (req, res) => {
      const { year, slugSpeaker } = req.params;

      return app.render(req, res, `/speakerdetail`, {
        year,
        slugSpeaker,
      });
    });

    srv.use(handler).listen(3000)
});

Then you can try to open url with incorrect data, it will automatically redirect to 404 page.

Reference: NextJS with custom-server-express

like image 165
Darryl RN Avatar answered Nov 15 '22 07:11

Darryl RN