Search code examples
reactjsreduxnext.jsnext-router

How to use router.replace inside the client side of your app?


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?


Solution

  • 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');
          }
       }
       ...
    }