Next.js Weiterleiten von / zu einer anderen Seite

15

Ich bin neu in Next.js und frage mich, wie ich zum Beispiel von der Startseite ( / ) zu / hello-nextjs umleiten kann . Sobald der Benutzer eine Seite lädt und danach feststellt, ob path === / redirect to / hello-nextjs ist

Im React-Router machen wir so etwas wie:

<Switch>
  <Route path="/hello-nextjs" exact component={HelloNextjs} />
  <Redirect to="/hello-nextjs" /> // or <Route path="/" exact render={() => <Redirect to="/hello-nextjs" />} />
</Switch>
Arthur
quelle
1
Wann soll die Umleitung erfolgen?
Nico
@ NicolòCozzani, sobald Benutzer eine Seite lädt. Und danach bestimmen Sie, ob url === / redirect to / hello-nextjs
Arthur

Antworten:

23

In können next.jsSie nach dem Laden der Seite mit Routerex umleiten :

import Router from 'next/router'

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

Oder mit Haken:

import React, { useEffect } from "react";
...
useEffect(() => {
   const {pathname} = Router
   if(pathname == '/' ){
       Router.push('/hello-nextjs')
   }
 });
Nico
quelle
Wie mache ich mit React Hooks?
Tessaracter
Ohne die Klassen zu benutzen
Tessaracter
2
@ Tessaracter Antwort aktualisiert
Nico
2
Was ist mit SSR? Die erste Seite blinkt mit diesem Ansatz
Eric Burel
@EricBurel das OP fragte deutlich "Sobald der Benutzer eine Seite lädt". Überprüfen Sie dies unter github.com/zeit/next.js/issues/649
Nico
16

Es gibt drei Ansätze.

1. Weiterleiten von Ereignissen oder Funktionen:

import Router from 'next/router';

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

2. Mit Haken umleiten:

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

const router = useRouter()

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

3. Mit Link umleiten:

Basierend auf Nextjs-Dokumenten ist das <a>Tag innerhalb des Links erforderlich, um beispielsweise in einem neuen Tab zu öffnen!

import Link from 'next/link';

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

Es gibt einige andere Optionen für das serverseitige Routing asPath. In allen beschriebenen Ansätzen können Sie asPath hinzufügen, um sowohl die Client- als auch die Serverseite umzuleiten.

Afsanefda
quelle
Hallo! Sie können sich meine Lösung ansehen
Arthur
Dies ist ein zwingender Ansatz. Es ist in Ordnung, bei Benutzeraktionen umzuleiten, jedoch nicht basierend auf einer Bedingung beim Laden der Seite, wie in der Frage angegeben.
Eric Burel
Ich habe nicht verstanden, was du meintest!?
Afsanefda
Die Frage betrifft die automatische Umleitung in Abhängigkeit vom aktuellen Pfadnamen der Route. Ihre Antworten sind gültig, aber in diesem Zusammenhang nicht anwendbar: Sie alle erfordern einen Benutzerklick.
Eric Burel
@ EricBurel, ja, das ist nicht was ich wollte, diese Antwort löst meine Frage nicht
Arthur
3

Die Antwort von @ Nico löst das Problem, wenn Sie Klassen verwenden.

Wenn Sie eine Funktion verwenden, können Sie diese nicht verwenden componentDidMount. Stattdessen können Sie React Hooks verwenden 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 eingeführt Haken. die sind viel schneller und effizienter als Klassen.

Tessaracter
quelle
Diese Ausgabe beschreibt, was ich als Ergebnis wollte
Arthur
@ Arthur. Oh, aber deine Frage sagt es nicht. Die Antwort von @Nico und mir ist genau die gleiche und ersetzt die <Switch>, in der Sie sie verwenden React-router. Auch <Switch>bietet keinen 303, 302 Statuscode. Nur Weiterleitungen
Tessaracter
Nun, ich denke das wird auch hier diskutiert. Ich habe gerade festgestellt, dass NextJS keinen Statuscode festlegt. github.com/zeit/next.js/issues/9443
Tessaracter
Bitte entfernen Sie Klassen. Es nützt hier nichts.
Pushp Singh
3

Halboffizielles Beispiel

Die with-cookie-authBeispiele leiten weiter getInitialProps. Ich bin nicht sicher, ob es sich um ein gültiges Muster handelt oder nicht, aber hier ist der Code:

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

Es behandelt sowohl die Server- als auch die Client-Seite. Der fetchAufruf ist derjenige, der tatsächlich das Authentifizierungstoken erhält. Möglicherweise möchten Sie diesen in eine separate Funktion kapseln.

Was ich stattdessen raten würde

 1. Weiterleiten beim serverseitigen Rendern (Flash während der SSR vermeiden)

Dies ist der häufigste Fall. Sie möchten an dieser Stelle umleiten, um zu vermeiden, dass die erste Seite beim ersten Laden blinkt.

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. Umleiten in componentDidMount (nützlich, wenn SSR deaktiviert ist, z. B. im statischen Modus)

Dies ist ein Fallback für das clientseitige Rendern.

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

Ich konnte es nicht vermeiden, die erste Seite im statischen Modus zu flashen. Fügen Sie diesen Punkt hinzu, da Sie während des statischen Builds nicht umleiten können, aber es scheint besser zu sein als die üblichen Ansätze. Ich werde versuchen zu bearbeiten, wenn ich Fortschritte mache.

Das vollständige Beispiel finden Sie hier

Relevantes Problem, das leider nur von einem Kunden beantwortet wird

Eric Burel
quelle
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
quelle
2
Dies sollte nicht die akzeptierte Antwort sein. Laut diesem github.com/zeit/next.js/issues/4931#issuecomment-512787861 sollten Sie nicht weiterleiten getInitialProps. @Afsanefda sollte die akzeptierte Antwort sein. Außerdem verwenden Sie next.js. Sie benötigen keinen Reaktionsrouter, um Routen zu organisieren. Next behandelt das bereits standardmäßig.
Rotimi-Best
3
@ rotimi-best, soweit ich mich erinnere, habe ich diesen Code aus dem Beispiel next.js übernommen. Außerdem habe ich keinen React-Router verwendet, er wurde als Beispiel für das vorgestellt, was ich bekommen wollte
Arthur
2
Dies ist eine gültige Antwort, jedoch nur mit SSR. In statischen Apps wird nicht umgeleitet. Bearbeiten: Eigentlich werden Sie Router.push hinzufügen, jedoch sollte die Clientseite Router.pushstattdessen in die Methoden des Komponentenlebenszyklus einsteigen
Eric Burel
1

Ich habe diese Funktionalität in meiner Next.JSApp implementiert, indem ich eine Stammseite definiert habe, die die Server- und Clientseite umleitet. Hier ist der Code für die Stammseite:

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
quelle