score:27

Accepted answer

with next.js (and any universal react rendering) your code is executing in two different environments. first in node (on the server) and then in a browser. next does some work to provide unified functions that run in both these environments but they're very different. next can't and doesn't keep this from you. it seems like you just loaded a page in your browser but here's a little more detail on what's really going on…

on the client/browser:

  • type url in the address bar (localhost:3000 or whatever), press enter.
  • get request goes out to the server (node).

on the server/node:

  • get request comes in.
  • node gives you a request and a response object.
    • maybe you have some express routing/middleware.
  • at some point next's render() function is called with the request and response objects.
  • next runs getinitialprops and passes in the request/response.
  • react rendertostring() is called which calls the following react lifecycle methods:
    • constructor()
    • componentwillmount()
    • render()
  • react creates a string of html that gets sent to the client.

^ this is node. you can't access window, you don't have fetch, and you can't use the next router. those are browser things.

back on the client:

  • html is downloaded and rendering begins.
  • links to js/css files in the html are downloaded/run.
    • this includes js code compiled by next.
  • react render() is run which associates the downloaded html (the dom) with a react virtual dom. the following react lifecycle methods will run:
    • constructor()
    • componentwillmount()
    • render()
    • componentdidmount()
  • all other lifecycle methods (updates) will run when props/state change.

^ this is the browser. you have window, you have fetch, you can use the next router. now you don't have the node request/response but that seems to catch people up less.

ref: component lifecycle

score:0

i found this https://www.npmjs.com/package/nextjs-redirect to be very simple and solved the issue for both client and server side.

pages/donate.js

import redirect from 'nextjs-redirect'
export default redirect('https://paypal.me')

score:1

to make sure the page never render, we need to add await new promise(() => {}) to end. the promise no needed resolve anything.

home.getinitialprops = async ({res}) => {
    if(res) {
      res.writehead(302, {location: '/dashboard'});
      res.end();
    } else {
      // window.location.href = '/dashboard';
      // or with spa redirect
      router.push('/dashboard');
    }
 
    await new promise(() => {});

    return {}
}

score:2

next/router is not available on the server that's way you get an error saying that router not found, next/router can only be used on the client side.

for you to redirect a user inside getinitialprops in the server you can use:

getinitialprops({server,res}){
 if(server)
  res.redirect('/');
 else
  router.push('/');
}

score:3

you can redirect from getinitialprops() like this:

import router from 'next/router'

static getinitialprops = (ctx) => {
    // on server
    if(typeof window === 'undefined'){
      res.writehead(302, {location: '/dashboard'})
      res.end()
    } else {
    // on client
      router.push('/dashboard')
    }
    return {}
}

see https://github.com/zeit/next.js/issues/649

score:4

the way works like @shi said, but there is not server in getinitialprops. instead of that, there should check window:

getinitialprops({res}){
 if(typeof window === 'undefined')
  res.redirect('/');
 else
  router.push('/');
}

Related Query

More Query from same tag