Redirecionar Next.js de / para outra página


15

Eu sou novo no Next.js e gostaria de saber como redirecionar da página inicial ( / ) para / hello-nextjs, por exemplo. Depois que o usuário carrega uma página e depois determina se o caminho === / redireciona para / hello-nextjs

No react-router , fazemos algo como:

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

11
quando você deseja que o redirecionamento aconteça?
— Nico

@ NicolòCozzani, uma vez que o usuário carrega uma página. E depois disso determinar se url === / redirecionamento para / Hello-nextjs
— Arthur

Respostas:


23

Em next.jsvocê pode redirecionar depois que a página é carregada usando Routerex:

import Router from 'next/router'

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

Ou com ganchos:

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

Como eu faço com ganchos React ??
— Tessaracter

Sem usar as classes
— Tessaracter

2
@Tessaracter resposta atualizada
— Nico

2
E o SSR? A página inicial está piscando com essa abordagem
— Eric Burel

@EricBurel, o OP perguntou claramente "Uma vez que o usuário carrega uma página", verifique este github.com/zeit/next.js/issues/649
— Nico

16

Existem três abordagens.

1.Redirecionar eventos ou funções:

import Router from 'next/router';

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

2. Redirecionar com ganchos:

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

const router = useRouter()

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

Redirecionar com link:

com base nos documentos do Nextjs, a <a>tag é necessária no link para itens como abrir em uma nova guia!

import Link from 'next/link';

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

Existem algumas outras opções para roteamento do lado do servidor asPath. em todas as abordagens descritas, você pode adicionar o asPath para redirecionar o cliente e o servidor.


Oi! Você pode olhar para a minha solução
— Arthur

Esta é uma abordagem imperativa. Não há problema em redirecionar a ação do usuário, mas não com base em uma condição no carregamento da página, conforme indicado na pergunta.
— Eric Burel 10/03

Eu não entendi o que você quis dizer !?
— Afsanefda 10/03

A questão é sobre o redirecionamento automático, dependendo do nome do caminho da rota atual. Suas respostas são válidas, mas não são aplicáveis ​​neste contexto: todas elas exigem um clique do usuário.
— Eric Burel 10/03

@ EricBurel, sim, isso não é o que eu queria, esta resposta não resolve minha pergunta
— Arthur

3

A resposta do @ Nico resolve o problema quando você está usando aulas.

Se você estiver usando a função, não poderá usar componentDidMount. Em vez disso, você pode usar Ganchos de reação 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
  )
}

Em 2019, a React introduziu ganchos. que são muito mais rápidos e eficientes que as classes.


Esta edição descreve o que eu queria como resultado
— Arthur

@Arthur . Ah, mas sua pergunta não diz isso. A resposta do @Nico e da minha é exatamente a mesma e substitui a <Switch>que você está usando React-router. Even <Switch>não fornece nenhum código de status 303, 302. Apenas redireciona
— Tessaracter 03/02

Bem, acho que o discutido aqui também. Acabei de perceber que o NextJS não define nenhum código de status. github.com/zeit/next.js/issues/9443
— Tessaracter

Por favor, remova as aulas. Não tem utilidade aqui.
— Pushp Singh 27/04

3

Exemplo semioficial

Os with-cookie-authexemplos são redirecionados getInitialProps. Não tenho certeza se é um padrão válido ou ainda não, mas aqui está o código:

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

Ele lida com o servidor e com o cliente. A fetchchamada é aquela que realmente obtém o token de autenticação; talvez você queira encapsular isso em uma função separada.

O que eu recomendaria

 1. Redirecione na renderização do servidor (evite flash durante o SSR)

Este é o caso mais comum. Você deseja redirecionar neste momento para evitar que a página inicial pisque no primeiro carregamento.

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. Redirecionar em componentDidMount (útil quando o SSR está desativado, por exemplo, no modo estático)

Este é um substituto para a renderização do lado do cliente.

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

Não pude evitar exibir a página inicial no modo estático. Adicione este ponto, porque você não pode redirecionar durante a compilação estática, mas parece melhor do que as abordagens usuais. Vou tentar editar à medida que progredir.

Exemplo completo está aqui

Problema relevante, que infelizmente acaba com uma resposta apenas do 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
Esta não deve ser a resposta aceita. De acordo com este github.com/zeit/next.js/issues/4931#issuecomment-512787861, você não deve redirecionar getInitialProps. @Afsanefda deve ser a resposta aceita. E você também está usando o next.js, que não precisa de um roteador de reação para organizar as rotas. Em seguida, já lida com isso por padrão.
— rotimi-best

3
@ rotimi-best, tanto quanto me lembro, peguei esse código no exemplo next.js. Além disso, eu não usei um roteador de reação, ele foi apresentado como um exemplo do que eu queria obter
— Arthur

2
Esta é uma resposta válida, mas apenas com SSR. Não será redirecionado em aplicativos estáticos. Edit: na verdade, você adicionou Router.push, no entanto, o lado do cliente Router.pushdeve entrar nos métodos de ciclo de vida do componente
— Eric Burel

1

Eu implementei essa funcionalidade no meu Next.JSaplicativo, definindo uma página raiz para redirecionar o servidor e o cliente. Aqui está o código para a página raiz:

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;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.