web-dev-qa-db-fra.com

Redirection vers Next.js depuis / vers une autre page

Je suis nouveau dans Next.js et je me demande comment rediriger de la page de démarrage (/) vers - / hello-nextjs par exemple. Une fois que l'utilisateur a chargé une page et après cela, déterminez si le chemin === / redirige vers / hello-nextjs

Dans react-router nous faisons quelque chose comme:

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

Dans next.js vous pouvez rediriger après le chargement de la page en utilisant Router ex:

import Router from 'next/router'

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

Ou avec des crochets:

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

Il existe trois approches.

1.Reportez sur les événements ou les fonctions:

import Router from 'next/router';

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

2. rediriger avec des crochets:

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

const router = useRouter()

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

3. rediriger avec Link:

basé sur Nextjs docs le <a> tag est nécessaire à l'intérieur du lien pour des choses comme ouvrir dans un nouvel onglet!

import Link from 'next/link';

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

Il existe d'autres options pour le routage côté serveur qui sont asPath. dans toutes les approches décrites, vous pouvez ajouter asPath pour rediriger le côté client et le côté serveur.

13
Afsanefda

Exemple semi-officiel

Le with-cookie-auth exemples de redirection dans getInitialProps. Je ne sais pas si c'est un modèle valide ou pas encore, mais voici le 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()
  }
}

Il gère à la fois le côté serveur et le côté client. L'appel fetch est celui qui obtient réellement le jeton d'authentification, vous voudrez peut-être l'encapsuler dans une fonction distincte.

Ce que je conseillerais à la place

C'est le cas le plus courant. Vous souhaitez rediriger à ce stade pour éviter que la page initiale ne clignote lors du premier chargement.

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 };
  };

Il s'agit d'un remplacement pour le rendu côté client.

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

Je ne pouvais pas éviter de flasher la page initiale en mode statique, ajoutez ce point, car vous ne pouvez pas rediriger pendant la construction statique, mais cela semble mieux que les approches habituelles. Je vais essayer d'éditer au fur et à mesure que je progresse.

L'exemple complet est ici

Problème pertinent, qui se termine malheureusement par une réponse du client uniquement

2
Eric Burel

La réponse de @ Nico résout le problème lorsque vous utilisez des classes.

Si vous utilisez la fonction, vous ne pouvez pas utiliser componentDidMount. À la place, vous pouvez utiliser 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
  )
}

En 2019 React introduit hooks. Qui sont beaucoup plus rapides et efficaces que les classes.

1
Tessaracter

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}/>
  }
}
0
Arthur