web-dev-qa-db-ja.com

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

私は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>
13
Arthur

next.jsリダイレクトできますページが読み込まれた後Router exを使用:

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')
   }
 });
13
Nico

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ドキュメントに基づく<a>タグは、新しいタブで開くなどの目的でリンク内に必要です。

import Link from 'next/link';

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

サーバーサイドルーティングには、asPathというオプションがいくつかあります。説明されているすべてのアプローチでは、クライアント側とサーバー側の両方をリダイレクトするasPathを追加できます。

13
Afsanefda

半公式の例

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呼び出しは、実際に認証トークンを取得する呼び出しです。これを別の関数にカプセル化することをお勧めします。

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

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

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

これは、クライアント側レンダリングのフォールバックです。

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

静的モードで最初のページをフラッシュすることは避けられませんでした。静的ビルド中にリダイレクトできないためですが、通常のアプローチよりも優れているようです。進行に合わせて編集してみます。

完全な例はこちら

関連する問題、悲しいことにクライアントのみの回答で終わる

2
Eric Burel

@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 introduced フックです。これはクラスよりもはるかに高速で効率的です。

1
Tessaracter

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}/>
  }
}
0
Arthur