Next.js从/重定向到另一个页面


15

我是Next.js的新手,并且想知道如何从起始页(/)重定向到/ hello-nextjs。用户加载页面后,确定路径是否=== /重定向至/ hello-nextjs

react-router中,我们执行以下操作:

<Switch>
  <Route path="/hello-nextjs" exact component={HelloNextjs} />
  <Redirect to="/hello-nextjs" /> // or <Route path="/" exact render={() => <Redirect to="/hello-nextjs" />} />
</Switch>

1
当您希望重定向发生时?
Nico

@NicolòCozzani,一旦用户加载页面。然后确定网址是否=== /重定向到/ hello-nextjs
Arthur

Answers:


23

next.js你可以重定向的页面加载后使用Router例如:

import Router from 'next/router'

componentDidMount(){
    const {pathname} = Router
    if(pathname == '/' ){
       Router.push('/hello-nextjs')
    }
}

或带钩子:

import React, { useEffect } from "react";
...
useEffect(() => {
   const {pathname} = Router
   if(pathname == '/' ){
       Router.push('/hello-nextjs')
   }
 });

我该如何使用React挂钩?
Tessaracter

不使用课程
Tessaracter

2
@Tessaracter答案已更新
Nico

2
SSR呢?这种方法在初始页面上
大放异彩

@EricBurel OP明确询问“用户加载页面一次”顺便检查一下github.com/zeit/next.js/issues/649
Nico

16

有三种方法。

1.重定向事件或功能:

import Router from 'next/router';

<button type="button" onClick={() => Router.push('/myroute')} />

2.使用钩子重定向:

import Router , {useRouter}  from 'next/router';

const router = useRouter()

<button type="button" onClick={() => router.push('/myroute')} />

3.使用链接重定向:

基于Nextjs docs,<a>在链接中需要标记,以便在新选项卡中打开之类的东西!

import Link from 'next/link';

<Link href="/myroute">
   <a>myroute</a>
</Link>

服务器端路由还有其他一些选择asPath。在所有描述的方法中,您都可以添加asPath来重定向客户端和服务器端。


嗨!您可以看看我的解决方案
亚瑟

这是当务之急。可以根据用户操作进行重定向,但不能根据问题中所述的页面加载条件进行重定向。
Eric Burel

我没有明白你的意思!
Afsanefda

问题是有关根据当前路由路径名自动重定向。您的答案有效,但在此情况下不适用:所有答案都需要用户点击。
Eric Burel

@EricBurel,是的,这不是我想要的,这个答案不能解决我的问题
Arthur

3

@Nico的答案可以解决您在使用类时的问题。

如果使用函数,则不能使用componentDidMount。相反,您可以使用React Hooks useEffect


import React, {useEffect} from 'react';

export default function App() {
  const classes = useStyles();

  useEffect(() => { 
    const {pathname} = Router
    if(pathname == '/' ){
      Router.push('/templates/mainpage1')
    }  
  }
  , []);
  return (
    null
  )
}

在2019年,React 引入了钩子。比类更快,更高效。


这个问题描述了我想要的结果
Arthur

@Arthur。哦,但是您的问题没有这么说。@Nico和我的答案完全相同,可以替代<Switch>您在中使用的答案React-router。甚至<Switch>不提供任何303、302状态代码。只是重定向
Tessaracter

好吧,我认为这里也进行了讨论。刚刚意识到NextJS不会设置任何状态代码。github.com/zeit/next.js/issues/9443
Tessaracter

请删除课程。这里没有用。
Pushp Singh

3

半官方的例子

这些with-cookie-auth示例在中重定向getInitialProps。我不确定这是否是有效的模式,但这是代码:

Profile.getInitialProps = async ctx => {
  const { token } = nextCookie(ctx)
  const apiUrl = getHost(ctx.req) + '/api/profile'

  const redirectOnError = () =>
    typeof window !== 'undefined'
      ? Router.push('/login')
      : ctx.res.writeHead(302, { Location: '/login' }).end()

  try {
    const response = await fetch(apiUrl, {
      credentials: 'include',
      headers: {
        Authorization: JSON.stringify({ token }),
      },
    })

    if (response.ok) {
      const js = await response.json()
      console.log('js', js)
      return js
    } else {
      // https://github.com/developit/unfetch#caveats
      return await redirectOnError()
    }
  } catch (error) {
    // Implementation or Network error
    return redirectOnError()
  }
}

它同时处理服务器端和客户端。该fetch调用实际上是获得auth令牌的调用,您可能希望将此封装为一个单独的函数。

我会建议

 1.在服务器端渲染上重定向(避免在SSR期间使用Flash)

这是最常见的情况。您要在此时进行重定向,以避免初始页面在首次加载时闪烁。

MyApp.getInitialProps = async appContext => {
    const currentUser = await getCurrentUser(); // define this beforehand
    const appProps = await App.getInitialProps(appContext);
    // check that we are in SSR mode (NOT static and NOT client-side)
    if (typeof window === "undefined" && appContext.ctx.res.writeHead) {
      if (!currentUser && !isPublicRoute(appContext.router.pathname)) {
          appContext.ctx.res.writeHead(302, { Location: "/account/login" });
          appContext.ctx.res.end();
      }
    }
    return { ...appProps, currentUser };
  };
 2.在componentDidMount中重定向(在禁用SSR(例如在静态模式下)时很有用)

这是客户端渲染的后备。

  componentDidMount() {
    const { currentUser, router } = this.props;
    if (!currentUser && !isPublicRoute(router.pathname)) {
      Router.push("/account/login");
    }
  }

我无法避免在静态模式下刷新初始页面,请添加这一点,因为您无法在静态构建过程中进行重定向,但这似乎比通常的方法要好。我会在取得进展时尝试进行编辑。

完整的例子在这里

相关问题,可悲的是最终只能由客户回答


1

redirect-to.ts

import Router from "next/router";

export default function redirectTo(
  destination: any,
  { res, status }: any = {}
): void {
  if (res) {
    res.writeHead(status || 302, { Location: destination });
    res.end();
  } else if (destination[0] === "/" && destination[1] !== "/") {
    Router.push(destination);
  } else {
    window.location = destination;
  }
}

_app.tsx

import App, {AppContext} from 'next/app'
import Router from "next/router"
import React from 'react'
import redirectTo from "../utils/redirect-to"


export default class MyApp extends App {
  public static async getInitialProps({Component, ctx}: AppContext): Promise<{pageProps: {}}> {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    if (ctx.pathname === "" || ctx.pathname === "/_error") {
      redirectTo("/hello-next-js", { res: ctx.res, status: 301 }); <== Redirect-To
      return {pageProps};
    }

    return {pageProps};
  }

  render() {
    const {Component, pageProps} = this.props;
    return <Component {...pageProps}/>
  }
}

2
这不应该是公认的答案。根据此github.com/zeit/next.js/issues/4931#issuecomment-512787861,您不应重定向getInitialProps。@Afsanefda应该是公认的答案。而且,您在使用next.js时,也不需要react路由器来组织路由。下一步已经默认处理了。
rotimi-best

3
@ rotimi-best,据我所记得,我从next.js示例中获取了这段代码。另外,我没有使用反应路由器,它只是我想要得到的一个例子
Arthur,

2
这是一个有效的答案,但仅适用于SSR。它不会在静态应用中重定向。编辑:实际上,您将添加Router.push,但是客户端Router.push应改为使用组件生命周期方法
Eric Burel

1

Next.JS通过定义一个用于重定向服务器端和客户端的根页面,在我的应用程序中实现了此功能。这是根页面的代码:

import { useEffect } from "react";
import Router from "next/router";

const redirectTo = "/hello-nextjs";

const RootPage = () => {
  useEffect(() => Router.push(redirectTo));
  return null;
};
RootPage.getInitialProps = (ctx) => {
  if (ctx.req) {
    ctx.res.writeHead(302, { Location: redirectTo });
    ctx.res.end();
  }
};

export default RootPage;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.