Next.js: Parametrized routes

Created on 18 Apr 2017  路  5Comments  路  Source: vercel/next.js

In refer to https://github.com/zeit/next.js/issues/1447 I need help to do the same things (with two params).
In my server.js (made with Express):

const express = require('express');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

app
  .prepare()
  .then(() => {
    const server = express();

    server.get('/', (req, res) => {
      return app.render(req, res, '/', req.query);
    })

    server.get('/page/:uid/:id', (req, res) => {
      console.log(req.query);
      return app.render(req, res, '/page', req.query);
    })

    server.get('*', (req, res) => {
      return handle(req, res);
    })

    server.listen(process.env.PORT, (err) => {
      if (err) { throw err; }

      console.log(`> Ready on port ${process.env.PORT}`);
    })
  });

my index.js (only one bit)

      {
        posts && posts.results
        ? posts.results.map(r => {
            return [
              <pre>{JSON.stringify(posts.results, null, 1)}</pre>,
              <Link href={`/page?uid=${r.uid}&id=${r.id}`} as={`/page/${r.uid}/${r.id}`} prefetch><a>link to post</a></Link>
            ]
          })

        : 'Loading'
      }

and my page.js

export default class extends React.Component {
  static async getInitialProps ({ req }) {
    console.log('>> params are: ', req.params, req.query, '\naaa\n');
    const { uid, id } = req.params;

    if (!uid || !id) {
      throw new Error('Missing a param in page route.');
    }

    const api = await getPrismicApi();
    const query = api.getByUID('post', uid);
    const result = await Promise.all([query]);

    return { q: result };
  }

  render () {
    <...>
  }
}

Refreshing page or navigating by direct link (eg: http://localhost:3400/page/first-post/WI8iTCcAAEpHT6ry) everything is ok but from index to x page it gave me the error Cannot read property 'params' of undefined. Any hints?

Most helpful comment

the req object in getInitialProps is only available on the server. Instead of using req try using query, it exists both on the server and client and should contain the parameters.

static async getInitialProps ({ query }) {
    console.log('>> params are: ', query);
}

The properties that are available in server and/or client side getInitialProps is documented here

All 5 comments

Are you using https://github.com/fridays/next-routes ? That seems to be where support for Express-style parameterized routes comes from. It looks like parameterized routes are not part of next.js "out of the box".

the req object in getInitialProps is only available on the server. Instead of using req try using query, it exists both on the server and client and should contain the parameters.

static async getInitialProps ({ query }) {
    console.log('>> params are: ', query);
}

The properties that are available in server and/or client side getInitialProps is documented here

Ok, thanks @reekris. In this way

export default class extends React.Component {
  static async getInitialProps ({ req, query }) {
    console.log(req ? 'via server' : 'via client');
    console.log('>> params are: ', req ? req.params : query , '\n\n');
    const { uid, id } = req ? req.params : query;

    if (!uid || !id) {
      throw new Error('Missing a param in page route.');
    }

    <...>

    return { q: result };
  }

  render () {
    <...>
  }
}

it works.

When I called the page directly in browser (http://localhost:3400/page/first-post/WI8iTCcAAEpHT6ry) it loads correctly but when go back to index and go back again to /page/first-post/WI8iTCcAAEpHT6ry using back and forward button in browser it gave me the error Missing a param in page route.

Am I missing anything about React / nextjs?

You need to make sure that your url params are passed into the querystring on the server, like this example. In your case, something like this:

    server.get('/page/:uid/:id', (req, res) => {
      const mergedQuery = Object.assign({}, req.query, req.params)
      return app.render(req, res, '/page', mergedQuery);
    })

Then your getInitialProps can get them straight from the query, regardless of where it loads.

It works, thanks! I missed that row in my example.

Was this page helpful?
0 / 5 - 0 ratings