Next.js Перенаправление с / на другую страницу

15

Я новичок в Next.js и мне интересно, как, например, перенаправить со стартовой страницы ( / ) в / hello-nextjs . После того, как пользователь загрузит страницу и после этого определит, будет ли путь === / перенаправить на / hello-nextjs

В реакции-роутере мы делаем что-то вроде:

<Switch>
  <Route path="/hello-nextjs" exact component={HelloNextjs} />
  <Redirect to="/hello-nextjs" /> // or <Route path="/" exact render={() => <Redirect to="/hello-nextjs" />} />
</Switch>
Артур
источник
1
когда ты хочешь чтобы редирект произошел?
Нико
@ NicolòCozzani, когда пользователь загружает страницу. И после этого определите, если URL === / перенаправить на / hello-nextjs
Артур

Ответы:

23

В то next.jsвы можете перенаправить после загрузки страницы , используя Routerпример:

import Router from 'next/router'

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

Или с крючками:

import React, { useEffect } from "react";
...
useEffect(() => {
   const {pathname} = Router
   if(pathname == '/' ){
       Router.push('/hello-nextjs')
   }
 });
Нико
источник
Как мне сделать с крючками React ??
Tessaracter
Без использования классов
Tessaracter
2
Ответ @Tessaracter обновлен
Нико
2
А как насчет ССР? Начальная страница мигает с этим подходом
Эрик Бурел
@EricBurel ОП четко спросил: «Как только пользователь загрузит страницу», проверьте это на github.com/zeit/next.js/issues/649
Нико
16

Есть три подхода.

1. Перенаправить на события или функции:

import Router from 'next/router';

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

2. Переадресация с крючками:

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

const router = useRouter()

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

3. Переадресация с помощью ссылки:

на основе документации Nextjs <a>тег необходим внутри ссылки для таких вещей, как открытие в новой вкладке!

import Link from 'next/link';

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

Есть несколько других вариантов маршрутизации на стороне сервера asPath. во всех описанных подходах вы можете добавить asPath для перенаправления как на стороне клиента, так и на стороне сервера.

Afsanefda
источник
Привет! Вы можете посмотреть на мое решение
Артур
Это императивный подход. Можно перенаправить действия пользователя, но не исходя из условия загрузки страницы, как указано в вопросе.
Эрик Бурел
Я не понял, что вы имели в виду !?
Афсанефда
Речь идет об автоматическом перенаправлении в зависимости от текущего пути. Ваши ответы действительны, но не применимы в этом контексте: все они требуют клика пользователем.
Эрик Бурел
@EricBurel, да, это не то, что я хотел, этот ответ не решает мой вопрос
Артур
3

Ответ @ Нико решает проблему, когда вы используете классы.

Если вы используете функцию, вы не можете использовать componentDidMount. Вместо этого вы можете использовать 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
  )
}

В 2019 году React представила крючки. которые намного быстрее и эффективнее, чем классы.

Tessaracter
источник
Эта проблема описывает то, что я хотел в результате
Артур
@ Артур. Ох, но ваш вопрос не говорит так. Ответ @Nico и мой точно такой же, и он заменяет тот, <Switch>который вы используете в React-router. Даже <Switch>не предоставляет 303, 302 кода состояния. Просто перенаправляет
Tessaracter
Ну, я думаю, что здесь обсуждается. Просто понял, что NextJS не устанавливает никакого кода состояния. github.com/zeit/next.js/issues/9443
Tessaracter
Пожалуйста, удалите классы. Это бесполезно здесь.
Pushp Singh
3

Полуофициальный пример

Эти with-cookie-authпримеры перенаправления в getInitialProps. Я не уверен, является ли это действительным шаблоном или нет, но вот код:

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

Он обрабатывает как на стороне сервера, так и на стороне клиента. fetchВызов является тот , который на самом деле получить маркер аутентификации, вы можете инкапсулировать это в отдельную функцию.

Что бы я посоветовал вместо

 1. Перенаправление при рендеринге на стороне сервера (избегайте прошивки во время SSR)

Это самый распространенный случай. Вы хотите перенаправить на этом этапе, чтобы избежать мигания начальной страницы при первой загрузке.

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. Перенаправление в componentDidMount (полезно, когда SSR отключен, например, в статическом режиме)

Это запасной вариант для рендеринга на стороне клиента.

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

Я не мог избежать перепрошивки начальной страницы в статическом режиме, добавив этот пункт, потому что вы не можете перенаправить во время статической сборки, но это кажется лучше, чем обычные подходы. Я постараюсь редактировать, как я делаю успехи.

Полный пример здесь

Актуальная проблема, которая, к сожалению, заканчивается только ответом клиента

Эрик Бурел
источник
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
Это не должно быть принятым ответом. Согласно этому github.com/zeit/next.js/issues/4931#issuecomment-512787861 вы не должны перенаправлять в getInitialProps. @Afsanefda должен быть принятым ответом. А также вы используете next.js, вам не нужен реагирующий маршрутизатор для организации маршрутов. Next уже обрабатывает это по умолчанию.
rotimi-best
3
@ rotimi-best, насколько я помню, я взял этот код из примера next.js. Кроме того, я не использовал реактивный маршрутизатор, он был представлен в качестве примера того, что я хотел получить
Артур
2
Это правильный ответ, но только с SSR. Он не будет перенаправлять в статических приложениях. Изменить: на самом деле вы добавите Router.push, однако на стороне клиента Router.pushвместо этого следует перейти к методам жизненного цикла компонента
Эрик Бурел
1

Я реализовал эту функцию в своем Next.JSприложении, определив корневую страницу, которая выполняет перенаправление на стороне сервера и на стороне клиента. Вот код для корневой страницы:

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
источник