从 React/Next.js 中的 getInitialProps 重定向

Redirecting from getInitalProps in React/Next.js

我正在使用 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

非常感谢任何有关此错误发生原因或修复方法的想法;)

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

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

getInitialProps({server,res}){
 if(server)
  res.redirect('/');
 else
  Router.push('/');
}

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

上client/browser:

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

上server/Node:

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

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

返回客户端:

  • HTML 已下载并开始渲染。
  • HTML 中 js/css 个文件的链接是 downloaded/run。
    • 这里包含了Next编译的js代码
  • React render() 是 运行,它将下载的 HTML(DOM)与 React 虚拟 DOM 相关联。以下 React 生命周期方法将 运行:
    • constructor()
    • componentWillMount()
    • render()
    • componentDidMount()
  • 所有其他生命周期方法(更新)将在 props/state 更改时 运行。

^ 这是浏览器。你有 window,你有 fetch,你可以使用 Next Router。现在您没有 Node request/response,但这似乎让人们不太感兴趣。

参考:Component lifecycle

方法和@Shi说的一样,但是getInitialProps中没有server。取而代之的是,应该检查 window:

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

您可以像这样从 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

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

pages/donate.js

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

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

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