私は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>
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')
}
});
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を追加できます。
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");
}
}
静的モードで最初のページをフラッシュすることは避けられませんでした。静的ビルド中にリダイレクトできないためですが、通常のアプローチよりも優れているようです。進行に合わせて編集してみます。
@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 フックです。これはクラスよりもはるかに高速で効率的です。
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}/>
}
}