Next.js Reindirizzare da / verso un'altra pagina


15

Sono nuovo in Next.js e mi chiedo come reindirizzare dalla pagina iniziale ( / ) a / ciao-nextjs per esempio. Una volta che l'utente carica una pagina e successivamente determina se percorso === / reindirizza a / hello-nextjs

In reag-router facciamo qualcosa del tipo:

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

1
quando vuoi che avvenga il reindirizzamento?
Nico,

@ NicolòCozzani, una volta che l'utente carica una pagina. E successivamente determina se url === / reindirizza a / hello-nextjs
Arthur

Risposte:


23

In next.jspuoi reindirizzare dopo che la pagina è stata caricata usando Routerex:

import Router from 'next/router'

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

O con ganci:

import React, { useEffect } from "react";
...
useEffect(() => {
   const {pathname} = Router
   if(pathname == '/' ){
       Router.push('/hello-nextjs')
   }
 });

Come posso fare con i ganci React ??
Tessaracter,

Senza usare le lezioni
Tessaracter il

2
@Tessaracter risposta aggiornata
Nico

2
Che dire di SSR? La pagina iniziale lampeggia con questo approccio
Eric Burel il

@EricBurel l'OP ha chiesto chiaramente "Una volta che l'utente carica una pagina" btw controlla questo github.com/zeit/next.js/issues/649
Nico

16

Esistono tre approcci.

1.Riretto su eventi o funzioni:

import Router from 'next/router';

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

2.Riretto con ganci:

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

const router = useRouter()

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

3.Riretto con collegamento:

basato sui documenti Nextjs, il <a>tag è necessario all'interno del link per cose come aprire in una nuova scheda!

import Link from 'next/link';

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

Ci sono alcune altre opzioni per il routing lato server che è asPath. in tutti gli approcci descritti puoi aggiungere asPath per reindirizzare sia il lato client che quello lato server.


Ciao! Puoi vedere la mia soluzione
Arthur,

Questo è un approccio imperativo. Va bene il reindirizzamento sull'azione dell'utente ma non sulla base di una condizione sul caricamento della pagina come indicato nella domanda.
Eric Burel,

Non ho capito cosa intendevi !?
Afsanefda,

La domanda riguarda il reindirizzamento automatico in base al percorso corrente. Le tue risposte sono valide ma non applicabili in questo contesto: richiedono tutte un clic dell'utente.
Eric Burel,

@EricBurel, sì, questo non è quello che volevo, questa risposta non risolve la mia domanda
Arthur

3

La risposta di @ Nico risolve il problema quando si utilizzano le classi.

Se si utilizza la funzione non è possibile utilizzare componentDidMount. Invece puoi usare 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
  )
}

Nel 2019 React ha introdotto i ganci. che sono molto più veloci ed efficienti delle classi.


Questo problema descrive ciò che volevo di conseguenza
Arthur

@Arthur. Oh, ma la tua domanda non lo dice. La risposta di @Nico e la mia sono esattamente le stesse ed è un sostituto di quello <Switch>che stai usando React-router. Anche <Switch>non fornisce alcun codice di stato 303, 302. Solo reindirizzamenti
Tessaracter

Bene, penso che anche qui discusso. Ho appena realizzato che NextJS non imposta alcun codice di stato. github.com/zeit/next.js/issues/9443
Tessaracter il

Rimuovi le classi. Non serve a niente qui.
Pushp Singh,

3

Esempio semi-ufficiale

Gli with-cookie-authesempi reindirizzano in getInitialProps. Non sono sicuro che si tratti di un modello valido o meno, ma ecco il codice:

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

Gestisce sia lato server che lato client. La fetchchiamata è quella che ottiene effettivamente il token di autenticazione, è possibile che si desideri incapsularla in una funzione separata.

Quello che consiglierei invece

 1. Reindirizzamento sul rendering lato server (evitare il flash durante SSR)

Questo è il caso più comune. Si desidera reindirizzare a questo punto per evitare che la pagina iniziale lampeggi al primo caricamento.

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. Reindirizzamento in componentDidMount (utile quando SSR è disabilitato, ad es. In modalità statica)

Questo è un fallback per il rendering lato client.

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

Non ho potuto evitare di eseguire il flashing della pagina iniziale in modalità statica aggiungendo questo punto, perché non è possibile reindirizzare durante la generazione statica, ma sembra meglio dei soliti approcci. Proverò a modificare mentre faccio progressi.

L'esempio completo è qui

Problema rilevante, che purtroppo finisce con una sola risposta del cliente


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
Questa non dovrebbe essere la risposta accettata. Secondo questo github.com/zeit/next.js/issues/4931#issuecomment-512787861 non dovresti reindirizzare getInitialProps. @Afsanefda dovrebbe essere la risposta accettata. E inoltre stai usando next.js non è necessario il router di reazione per organizzare i percorsi. Next lo gestisce già per impostazione predefinita.
Rotimi-best

3
@ rotimi-best, per quanto mi ricordo, ho preso questo codice dall'esempio next.js. Inoltre, non ho usato un reagente-router, è stato presentato come un esempio di ciò che volevo ottenere
Arthur,

2
Questa è una risposta valida ma solo con SSR. Non reindirizzerà nelle app statiche. Modifica: in realtà aggiungerai Router.push, tuttavia il lato client Router.pushdovrebbe andare invece nei metodi del ciclo di vita dei componenti
Eric Burel

1

Ho implementato questa funzionalità nella mia Next.JSapp definendo una pagina principale che reindirizza il lato server e il lato client. Ecco il codice per la pagina principale:

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.