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.