Next.js /から別のページへのリダイレクト


15

私は中に新たなんだNext.jsと私は、スタートページ(からリダイレクトする方法を思ったんだけど/へ)/ハローnextjs例えば。ユーザーがページをロードした後、パス=== / / hello-nextjsにリダイレクトするかどうかを決定します

反応し、ルータ、我々は次のように実行します。

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

1
リダイレクトが発生したい場合は?
ニコ

@NicolòCozzani、ユーザーがページをロードすると。その後、url === / / hello-nextjsにリダイレクトするかどうかを決定します
Arthur

回答:


23

では ex を使用してページが読み込ま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の回答が更新されました
ニコ

2
SSRはどうですか?最初のページはこのアプローチで点滅しています
Eric Burel

@EricBurel OPは「ユーザーがページをロードしたら」と明確に尋ねましたが、このgithub.com/zeit/next.js/issues/649を
ニコ

16

3つのアプローチがあります。

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を追加できます。


こんにちは!私のソリューションを見ることができます
Arthur

これは必須のアプローチです。ユーザーのアクションにリダイレクトしても問題ありませんが、質問に記載されているように、ページ読み込みの条件に基づいていません。
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 フックを導入しました。クラスよりもはるかに高速で効率的です。


この問題は、私が結果として欲しかったことを説明しています
アーサー

@アーサー。ああ、でもあなたの質問はそうではありません。@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コールは、認証トークンを取得し、実際に、あなたは別の関数にこれをカプセル化する場合がありますということです。

代わりに私がアドバイスすること

 1.サーバー側のレンダリングでリダイレクトする(SSR中のフラッシュは避けてください)

これは最も一般的なケースです。この時点でリダイレクトして、最初のロード時に最初のページが点滅しないようにします。

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を使用しているため、ルートを整理するためにルーターを反応させる必要はありません。Nextはすでにデフォルトでそれを処理しています。
rotimi-best

3
@ rotimi-best、私が覚えている限り、このコードはnext.jsの例から取っています。また、react-routerは使用しませんでした。これは、取得したいものの例として提示されたものです
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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.