Как использовать router.replace на стороне клиента вашего приложения?

Я пытаюсь использовать маршрутизатор Next.js для перенаправления неавторизованных пользователей для доступа к определенным страницам, которые заключены в AdminLayout компонент, но я получил эту ошибку.

Ошибка: экземпляр маршрутизатора не найден. Вы должны использовать "next/router" только на стороне клиента вашего приложения.

// 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);

Как это исправить?

4 ответа

Решение

render метод также выполняется на сервере, поэтому вы получаете исключение.

Обычно не рекомендуется добавлять побочные эффекты (например, перенаправления) вrender метод.

Вы должны положить это внутрь componentDidMount который работает только на стороне клиента.

// 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);

Если вы хотите перенаправить на стороне сервера, вам нужно будет использовать getInitialProps / getServerPropsкоторый работает на сервере, эти методы на стороне сервера он получает серверrequest & response который позволяет вам перенаправлять с сервера.

class AdminLayout extends React.Component {
   static getInitialProps ({ res }) {
      if(someCondition) {
        res.redirect('/your-path');
      }
   }
   ...
}

Если кто-то сталкивается с той же ошибкой, но в другой ситуации, убедитесь, что вы правильно используете следующий маршрутизатор.

мои расширения vscode импортировали его как

import router from 'next/router

Когда это должно быть

import {useRouter} from 'next/router'

а затем использовать его позже, как

const router = useRouter()

Вы можете реализовать эту строку перед вызовом router.push("/"):

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

Это предотвратит отправку вашего маршрутизатора, когда клиенты все еще выполняют рендеринг.

если вы используете его внутри функции, у вас может быть такая же ошибка, как и у меня,

Не делайте так:

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

Вместо этого сделайте это так:

      Checkout.then(res => {
const router = useRouter() //correct
router...(URL)
})
Другие вопросы по тегам