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>
Arthur
fonte
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')
   }
 });
Nico
fonte
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.

Afsanefda
fonte
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.

Tessaracter
fonte
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

Eric Burel
fonte
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
fonte
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;
BruceHill
fonte