14

I'm trying to use Next.js router to redirect unauthorized users from accessing certain pages that are wrapped inside the AdminLayout component, but I got this error.

Error: No router instance found. You should only use "next/router" inside the client side of your app.

No router instance found

// Other imports
import Router from "next/router";

class AdminLayout extends React.Component {
  render() {
    const { currentUser } = this.props;

    if (currentUser === undefined) {
      console.log(currentUser);
      return null;
    }

    if (currentUser == null) {
      console.log(currentUser);
      //this is how I tried to redirect
      Router.replace("/admin/login");
    }
    return (
      // Other irrelevant code
    );
  }
}

const mapStateToProps = (state) => ({
  currentUser: state.user.currentUser,
});

export default connect(mapStateToProps)(AdminLayout);

Any way to fix this?

4 Answers4

8

render method is executed in the server as well, therefore you get the exception.

Usually it is a bad practice to put side effect (such as redirects) in the render method.

You should put it inside componentDidMount which runs only on the client side.

// Other imports
import Router from "next/router";

class AdminLayout extends React.Component {
  componentDidMount() {
    const {currentUser} = this.props;

    if (currentUser === undefined) {
      console.log(currentUser);
      return null;
    }

    if (currentUser == null) {
      console.log(currentUser);
      //this is how I tried to redirect
      Router.replace('/admin/login');
    }
  }
  render() {
    const {currentUser} = this.props;

    if (currentUser === undefined) {
      console.log(currentUser);
      return null;
    }
    return (
      // Other irrelevant code
    );
  }
}

const mapStateToProps = (state) => ({
  currentUser: state.user.currentUser,
});

export default connect(mapStateToProps)(AdminLayout);

If you want to redirect on in the server side you will need to use getInitialProps / getServerProps which runs on the server, these methods on the server side it gets the server request & response which enables you to redirect from the server.

class AdminLayout extends React.Component {
   static getInitialProps ({ res }) {
      if(someCondition) {
        res.redirect('/your-path');
      }
   }
   ...
}
felixmosh
  • 32,615
  • 9
  • 69
  • 88
3

You can implement this line before call the router.push("/"):

if (typeof window === "undefined") return null;

This will prevent your router from push when the clients still's rendering

2

If anyone's facing the same error but a different situation, make sure you're using next router correctly.

my vscode extensions imported it like

import router from 'next/router

When it should be

import {useRouter} from 'next/router'

and then use it later like

const router = useRouter()

Vito Medlej
  • 131
  • 2
  • 8
0

if you're using it inside a function you might've got the same error as I did,

Don't do it like this:

const router = useRouter() //wrong
Checkout.then(res => {
router...(URL)
})

Instead, do it like this:

Checkout.then(res => {
const router = useRouter() //correct
router...(URL)
})