Next.js Chuyển hướng từ / đến một trang khác


15

Tôi là người mới trong Next.js và tôi đang tự hỏi làm thế nào để chuyển hướng từ trang bắt đầu ( / ) sang / hello-nextjs chẳng hạn. Khi người dùng tải một trang và sau đó xác định xem path === / redirect đến / hello-nextjs

Trong bộ định tuyến phản ứng, chúng tôi làm một cái gì đó như:

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

1
Khi bạn muốn điều đó xảy ra?
Nico

@ NicolòCozzani, một khi người dùng tải một trang. Và sau đó xác định xem url === / redirect đến / hello-nextjs
Arthur

Câu trả lời:


23

Trong next.jsbạn có thể chuyển hướng sau khi trang được tải bằng Routerex:

import Router from 'next/router'

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

Hoặc với Móc:

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

Làm thế nào để tôi làm với móc React ??
Tessaracter

Không sử dụng các lớp học
Tessaracter

2
@Tessaracter đã cập nhật câu trả lời
Nico

2
SSR thì sao? Trang ban đầu đang nhấp nháy với cách tiếp cận này
Eric Burel

@EricBurel OP đã hỏi rõ ràng "Khi người dùng tải một trang" btw hãy kiểm tra github.com/zeit/next.js/issues/649
Nico

16

Có ba cách tiếp cận.

1. Chuyển hướng về các sự kiện hoặc chức năng:

import Router from 'next/router';

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

2. Chuyển hướng với móc:

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

const router = useRouter()

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

3. Chuyển hướng với Liên kết:

dựa trên tài liệu Nextjs, <a>thẻ không cần thiết bên trong liên kết cho những thứ như mở trong một tab mới!

import Link from 'next/link';

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

Có một số tùy chọn khác để định tuyến máy chủ asPath. trong tất cả các cách tiếp cận được mô tả, bạn có thể thêm asPath để chuyển hướng cả phía máy khách và máy chủ.


Chào! Bạn có thể nhìn vào giải pháp của tôi
Arthur

Đây là một cách tiếp cận bắt buộc. Bạn có thể chuyển hướng theo hành động của người dùng nhưng không dựa trên điều kiện tải trang như đã nêu trong câu hỏi.
Eric Burel

Tôi không hiểu ý bạn!?
Afsanefda

Câu hỏi là về việc tự động chuyển hướng tùy thuộc vào tên đường dẫn hiện tại. Câu trả lời của bạn là hợp lệ nhưng không được hoan nghênh trong ngữ cảnh này: tất cả đều yêu cầu người dùng nhấp chuột.
Eric Burel

@EricBurel, vâng, đây không phải là điều tôi muốn, câu trả lời này không giải quyết được câu hỏi của tôi
Arthur

3

Câu trả lời của @ Nico giải quyết vấn đề khi bạn đang sử dụng các lớp học.

Nếu bạn đang sử dụng chức năng, bạn không thể sử dụng componentDidMount. Thay vào đó bạn có thể sử dụng React Hook 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
  )
}

Năm 2019 React giới thiệu móc. đó là nhanh hơn và hiệu quả hơn so với các lớp học.


Vấn đề này mô tả những gì tôi muốn là kết quả
Arthur

@Arthur. Ồ, nhưng câu hỏi của bạn không nói như vậy. Câu trả lời của @Nico và của tôi hoàn toàn giống nhau và là sự thay thế cho câu <Switch>hỏi mà bạn đang sử dụng React-router. Thậm chí <Switch>không cung cấp bất kỳ mã trạng thái 303, 302. Chỉ cần chuyển hướng
Tessaracter

Vâng, tôi nghĩ rằng các cuộc thảo luận ở đây quá. Chỉ cần nhận ra rằng NextJS không đặt bất kỳ mã trạng thái nào. github.com/zeit/next.js/issues/9443
Tessaracter

Vui lòng xóa các lớp. Nó không được sử dụng ở đây.
Pushp Singh

3

Ví dụ bán chính thức

Các with-cookie-authví dụ chuyển hướng trong getInitialProps. Tôi không chắc đó có phải là mẫu hợp lệ hay không, nhưng đây là mã:

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

Nó xử lý cả phía máy chủ và phía máy khách. Cuộc fetchgọi là cuộc gọi thực sự nhận được mã thông báo xác thực, bạn có thể muốn gói nó thành một chức năng riêng biệt.

Thay vào đó tôi sẽ khuyên gì

 1. Chuyển hướng trên kết xuất phía máy chủ (tránh flash trong SSR)

Đây là trường hợp phổ biến nhất. Bạn muốn chuyển hướng vào thời điểm này để tránh trang ban đầu nhấp nháy khi tải lần đầu tiên.

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. Chuyển hướng trong thành phầnDidMount (hữu ích khi SSR bị tắt, ví dụ như ở chế độ tĩnh)

Đây là một dự phòng cho kết xuất phía máy khách.

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

Tôi không thể tránh việc flash trang ban đầu ở chế độ tĩnh thêm điểm này, vì bạn không thể chuyển hướng trong quá trình xây dựng tĩnh, nhưng có vẻ tốt hơn các cách tiếp cận thông thường. Tôi sẽ cố gắng chỉnh sửa khi tôi tiến bộ.

Ví dụ đầy đủ là đây

Vấn đề có liên quan, đáng buồn kết thúc với một khách hàng chỉ trả lời


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
Đây không phải là câu trả lời được chấp nhận. Theo github.com/zeit/next.js/issues/4931#issuecomment-512787861 này, bạn không nên chuyển hướng vào getInitialProps. @Afsanefda nên là câu trả lời được chấp nhận. Và bạn cũng đang sử dụng next.js, bạn không cần bộ định tuyến phản ứng để tổ chức các tuyến đường. Tiếp theo đã xử lý theo mặc định.
rotimi-best

3
@ rotimi-best, theo như tôi nhớ, tôi đã lấy mã này từ ví dụ next.js. Ngoài ra, tôi không sử dụng bộ định tuyến phản ứng, nó được trình bày như một ví dụ về những gì tôi muốn nhận
Arthur

2
Đây là một câu trả lời hợp lệ nhưng chỉ với SSR. Nó sẽ không chuyển hướng trong các ứng dụng tĩnh. Chỉnh sửa: thực sự bạn sẽ thêm Router.push, tuy nhiên phía khách hàng Router.pushnên đi vào các phương thức vòng đời thành phần thay vào đó
Eric Burel

1

Tôi đã triển khai chức năng này trong Next.JSứng dụng của mình bằng cách xác định trang gốc, phía máy chủ chuyển hướng và phía máy khách. Đây là mã cho trang gốc:

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.