Pengalihan Next.js dari / ke halaman lain

15

Saya baru di Next.js dan saya bertanya-tanya bagaimana cara mengalihkan dari halaman awal ( / ) ke / hello-nextjs misalnya. Setelah pengguna memuat halaman dan setelah itu menentukan apakah path === / redirect ke / hello-nextjs

Di react-router kami melakukan sesuatu seperti:

<Switch>
  <Route path="/hello-nextjs" exact component={HelloNextjs} />
  <Redirect to="/hello-nextjs" /> // or <Route path="/" exact render={() => <Redirect to="/hello-nextjs" />} />
</Switch>
Arthur
sumber
1
ketika Anda ingin pengalihan terjadi?
Nico
@ NicolòCozzani, setelah pengguna memuat halaman. Dan setelah itu menentukan apakah url === / redirect ke / hello-nextjs
Arthur

Jawaban:

23

Di next.jsAnda dapat mengarahkan ulang setelah halaman dimuat menggunakan Routerex:

import Router from 'next/router'

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

Atau dengan Kait:

import React, { useEffect } from "react";
...
useEffect(() => {
   const {pathname} = Router
   if(pathname == '/' ){
       Router.push('/hello-nextjs')
   }
 });
Nico
sumber
Bagaimana saya melakukan dengan React hooks ??
Tessaracter
Tanpa menggunakan kelas
Tessaracter
2
@Tessaracter menjawab diperbarui
Nico
2
Bagaimana dengan RSK? Halaman awal berkedip dengan pendekatan ini
Eric Burel
@EricBurel OP dengan jelas bertanya "Setelah pengguna memuat halaman" btw periksa github.com/zeit/next.js/issues/649
Nico
16

Ada tiga pendekatan.

1.Redirect pada acara atau fungsi:

import Router from 'next/router';

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

2. Direct dengan kait:

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

const router = useRouter()

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

3. Langsung dengan Tautan:

berdasarkan pada dokumen Nextjs, <a>tag tersebut diperlukan di dalam tautan untuk hal-hal seperti buka di tab baru!

import Link from 'next/link';

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

Ada beberapa opsi lain untuk perutean serveride yang asPath. dalam semua pendekatan yang dijelaskan Anda dapat menambahkan asPath untuk mengarahkan kembali sisi klien dan server.

Afsanefda
sumber
Hai! Anda dapat melihat solusi saya
Arthur
Ini adalah pendekatan imperatif. Tidak apa-apa untuk mengarahkan kembali pada tindakan pengguna tetapi tidak didasarkan pada kondisi pada pemuatan halaman seperti yang dinyatakan dalam pertanyaan.
Eric Burel
Aku tidak mengerti maksudmu !?
Afsanefda
Pertanyaannya adalah tentang pengalihan otomatis tergantung pada pathname rute saat ini. Jawaban Anda valid tetapi tidak dapat diterapkan dalam konteks ini: semuanya memerlukan klik pengguna.
Eric Burel
@EricBurel, ya, ini bukan yang saya inginkan, jawaban ini tidak menyelesaikan pertanyaan saya
Arthur
3

Jawaban @ Nico memecahkan masalah ketika Anda menggunakan kelas.

Jika Anda menggunakan fungsi, Anda tidak dapat menggunakan componentDidMount. Sebagai gantinya Anda dapat menggunakan 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
  )
}

Pada 2019 Bereaksi memperkenalkan kait. yang jauh lebih cepat dan efisien daripada kelas.

Tessaracter
sumber
Masalah ini menjelaskan apa yang saya inginkan sebagai hasilnya
Arthur
@Arthur. Oh, tapi pertanyaanmu tidak mengatakannya. Jawaban oleh @Nico dan saya persis sama dan merupakan pengganti untuk <Switch>yang Anda gunakan React-router. Bahkan <Switch>tidak menyediakan kode status 303, 302.
Arahan
Yah, saya pikir yang dibahas di sini juga. Baru menyadari bahwa NextJS tidak menetapkan kode status apa pun. github.com/zeit/next.js/issues/9443
Tessaracter
Silakan hapus kelas. Tidak ada gunanya di sini.
Pushp Singh
3

Contoh semi resmi

The with-cookie-authcontoh redirect di getInitialProps. Saya tidak yakin apakah ini pola yang valid atau belum, tapi ini kodenya:

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()
  }
}

Ini menangani sisi server dan sisi klien. Itufetch panggilan adalah salah satu yang benar-benar mendapatkan token auth, Anda mungkin ingin merangkum ini menjadi fungsi yang terpisah.

Apa yang saya sarankan sebagai gantinya

 1. Redirect pada render sisi server (hindari flash selama SSR)

Ini adalah kasus yang paling umum. Anda ingin mengarahkan pada titik ini untuk menghindari halaman awal berkedip saat memuat pertama.

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. Redirect di componentDidMount (berguna ketika SSR dinonaktifkan, misalnya dalam mode statis)

Ini adalah fallback untuk rendering sisi klien.

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

Saya tidak bisa menghindari mem-flash halaman awal dalam mode statis menambahkan titik ini, karena Anda tidak dapat mengarahkan ulang selama pembuatan statis, tetapi tampaknya lebih baik daripada pendekatan yang biasa. Saya akan mencoba mengedit saat saya membuat kemajuan.

Contoh lengkap ada di sini

Masalah yang relevan, yang sayangnya berakhir dengan jawaban klien saja

Eric Burel
sumber
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}/>
  }
}
Arthur
sumber
2
Ini seharusnya bukan jawaban yang diterima. Menurut github.com/zeit/next.js/issues/4931#issuecomment-512787861 ini, Anda tidak boleh mengalihkan getInitialProps. @Afsanefda harus menjadi jawaban yang diterima. Dan juga Anda menggunakan next.js Anda tidak perlu bereaksi router untuk mengatur rute. Selanjutnya sudah menangani itu secara default.
rotimi-best
3
@ rotimi-best, sejauh yang saya ingat, saya mengambil kode ini dari contoh next.js. Juga, saya tidak menggunakan router reaksi, itu disajikan sebagai contoh dari apa yang ingin saya dapatkan
Arthur
2
Ini adalah jawaban yang valid tetapi dengan SSR saja. Itu tidak akan mengarahkan ulang di aplikasi statis. Sunting: sebenarnya itu akan Anda tambahkan Router.push, namun sisi klien Router.pushharus pergi ke metode siklus hidup komponen sebagai gantinya
Eric Burel
1

Saya telah menerapkan fungsi ini di Next.JSaplikasi saya dengan mendefinisikan halaman root ini apakah sisi server redirect dan sisi klien. Ini kode untuk halaman root:

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;
BruceHill
sumber