5

我正在使用 React 和 Next.js 并尝试在该页面的数据不可用时从页面重定向用户Router.push('/another-page')

为此,我正在检查状态代码getInitalProps并应用条件。它看起来像这样:

  const statusCode = action.currentArticle ? 200 : 404

  if (isServer) res.statusCode = statusCode

  if (statusCode === 404) {
    Router.push('/')
  }

状态代码已正确设置,并使其在条件范围内,此时我收到此错误:No router instance found. You should only use "next/router" inside the client side of your app.

实际上,无论我尝试重定向组件生命周期事件的哪个位置,我都会遇到相同的错误,并且在线获得的有关此错误的信息很少。

getInitalProps可以在 next.js wiki 中看到重定向模式: HERE

非常感谢有关为什么会发生此错误或如何解决此错误的任何想法;)

4

6 回答 6

28

使用 Next.js(和任何通用反应渲染),您的代码在两个不同的环境中执行。首先在 Node 中(在服务器上),然后在浏览器中。Next 做了一些工作来提供在这两种环境中运行的统一功能,但它们非常不同。Next 不能也不会向您隐瞒。看起来您刚刚在浏览器中加载了一个页面,但这里有更多关于实际情况的详细信息……</p>

在客户端/浏览器上:

  • 在地址栏中输入 url(localhost:3000 或其他),按 Enter。
  • GET 请求发送到服务器(节点)。

在服务器/节点上:

  • GET 请求进来。
  • Node 给你一个请求和一个响应对象。
    • 也许你有一些 Express 路由/中间件。
  • 在某些时候 Next 的render()函数被请求和响应对象调用。
  • Next 运行getInitialProps并传入请求/响应。
  • ReactrenderToString()被调用,它调用以下 React 生命周期方法:
    • constructor()
    • componentWillMount()
    • render()
  • React 创建一个发送给客户端的 HTML 字符串。

^ 这是节点。你不能访问window,你没有fetch,你也不能使用 Next Router。这些是浏览器的东西。

回到客户端:

  • 下载 HTML 并开始渲染。
  • 下载/运行 HTML 中 js/css 文件的链接。
    • 这包括由 Next 编译的 js 代码。
  • 运行React render(),它将下载的 HTML(DOM)与 React 虚拟 DOM 相关联。以下 React 生命周期方法将运行:
    • constructor()
    • componentWillMount()
    • render()
    • componentDidMount()
  • 所有其他生命周期方法(更新)将在道具/状态更改时运行。

^ 这是浏览器。你有window,你有fetch,你可以使用下一个路由器。现在您没有 Node 请求/响应,但这似乎很少能赶上人们。

参考:组件生命周期

于 2018-03-27T21:13:31.327 回答
3

next/router 在服务器上不可用,这样您会收到一条错误消息,指出找不到路由器,next/router 只能在客户端使用。

为了在服务器的 getInitialProps 中重定向用户,您可以使用:

getInitialProps({server,res}){
 if(server)
  res.redirect('/');
 else
  Router.push('/');
}
于 2018-03-15T17:00:59.640 回答
3

这种方式就像@Shi 说的那样工作,但server在getInitialProps 中没有。取而代之的是,应该检查window

getInitialProps({res}){
 if(typeof window === 'undefined')
  res.redirect('/');
 else
  Router.push('/');
}
于 2019-07-08T03:34:29.050 回答
2

您可以像这样重定向getInitialProps()

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 {}
}

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

于 2020-04-27T01:18:23.957 回答
1

为了确保页面永远不会呈现,我们需要添加await new Promise(() => {})到 end。承诺无需解决任何问题。

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 {}
}
于 2021-04-23T10:01:42.843 回答
0

我发现这个https://www.npmjs.com/package/nextjs-redirect非常简单,解决了客户端和服务器端的问题。

页面/donate.js

import redirect from 'nextjs-redirect'
export default redirect('https://paypal.me')
于 2020-12-23T10:28:59.297 回答