JavaScript >> Javascript 文檔 >  >> Tags >> Next.js

如何使用 Next.js 處理經過身份驗證的路由

如何創建一個可以根據用戶的登錄或註銷狀態有條件地重定向用戶的 HOC(高階組件)。

在 Next.js 中,默認情況下,您的所有路由都被視為相同。

雖然您的特定應用可能包含僅供登錄用戶使用的頁面或路由,但 Next.js 開箱即用 提供一種基於用戶身份驗證狀態隔離這些頁面的方法。

這是意料之中的,因為 Next.js 旨在處理一組簡單的、定義明確的任務。雖然它可以 用作應用程序的前端(例如在 CheatCode 的 Next.js 樣板中),傳統上它用於生成靜態營銷網站或由無頭 CMS 支持的網站。

幸運的是,解決這個問題並不太複雜。為了解決這個問題,我們將實現兩個組件:

  1. 00 這將是一個返回 React 組件的函數,該組件包含對用戶身份驗證狀態的條件檢查以及在用戶不可用時重定向。
  2. 18 這將是一個返回 React 組件的函數,該組件包含對用戶身份驗證狀態的條件檢查以及如果用戶存在則重定向。

實現一個經過身份驗證的路由組件

首先,讓我們構建 HOC 的框架並討論它是如何工作的:

/components/AuthenticatedRoute/index.js

import React from "react";

const authenticatedRoute = (Component = null, options = {}) => {
 // We'll handle wrapping the component here.
};

export default authenticatedRoute;

在這裡,我們導出一個帶有兩個參數的普通 JavaScript 函數:一個 React 25 作為第一個參數和 30 的對象 作為第二個。 45 表示我們想要有條件地渲染的受保護頁面的組件。

當我們去使用它時,我們會做這樣的事情:

/pages//index.js

import authenticatedRoute from '../../components/AuthenticatedRoute';

const MyComponent = () => {
  [...]
};

export default authenticatedRoute(MyComponent, { pathAfterFailure: '/login' })

接下來,讓我們用核心包裝組件填充我們的 HOC:

/components/AuthenticatedRoute/index.js

import React from "react";

const authenticatedRoute = (Component = null, options = {}) => {
  class AuthenticatedRoute extends React.Component {
    state = {
      loading: true,
    };

    render() {
      const { loading } = this.state;

      if (loading) {
        return <div />;
      }

      return <Component {...this.props} />;
    }
  }

  return AuthenticatedRoute;
};

export default authenticatedRoute;

在這裡,我們填充了我們的 57 帶有基於類的 React 組件的函數體。這裡的想法是我們想要利用狀態和——接下來——60 類的函數,以便我們可以決定是否要渲染傳遞的 76 , 或者, 將用戶重定向離開它。

/components/AuthenticatedRoute/index.js


import React from "react";
import Router from "next/router";

const authenticatedRoute = (Component = null, options = {}) => {
  class AuthenticatedRoute extends React.Component {
    state = {
      loading: true,
    };

    componentDidMount() {
      if (this.props.isLoggedIn) {
        this.setState({ loading: false });
      } else {
        Router.push(options.pathAfterFailure || "/login");
      }
    }

    render() {
      const { loading } = this.state;

      if (loading) {
        return <div />;
      }

      return <Component {...this.props} />;
    }
  }

  return AuthenticatedRoute;
};

export default authenticatedRoute;

現在,使用我們的 80 補充說,我們可以看到我們的核心行為實現了。在裡面,我們只想知道“是否有登錄用戶?”如果有 一個登錄的用戶,我們想說“繼續渲染傳遞的 97 ." 我們可以在 108 中看到這一點 113 的方法 組件。

在這裡,我們說,只要 121130 , 只返回一個空的 149 (或者,不向用戶顯示任何內容)。如果我們不是 加載,只需運行 152 162 底部的語句 .

這樣做的目的是說“直到我們知道我們有一個登錄用戶,什麼都不顯示,如果我們 有一個登錄用戶,向他們展示他們正在嘗試訪問的頁面。”

返回 176180 聲明,我們說“好吧,看起來用戶沒有登錄,所以讓我們重定向他們。”為了在這個例子中做重定向,我們使用內置的 Next.js 路由器為我們做重定向,但是你可以使用任何你喜歡的 JavaScript 或 React 路由器(例如,如果我們使用 React 路由器,我們會做 195 .

說得通?因此,如果我們有用戶,請向他們展示組件。如果我們沒有用戶,將他們重定向到另一個路由。

確定登錄狀態

現在,從技術上講,這就是我們所要做的。但是您可能想知道“我們如何知道用戶是否已登錄?”這就是您自己的應用程序的用武之地。在此示例中,我們使用 CheatCode Next.js 樣板,它依賴於在全球 Redux 商店中存在的經過身份驗證的用戶(如果可用)。

為了讓這一切更加具體,讓我們現在來看看這個設置:

/components/AuthenticatedRoute/index.js

import React from "react";
import Router from "next/router";
import { connect } from "react-redux";

const authenticatedRoute = (Component = null, options = {}) => {
  class AuthenticatedRoute extends React.Component {
    state = {
      loading: true,
    };

    componentDidMount() {
      if (this.props.isLoggedIn) {
        this.setState({ loading: false });
      } else {
        Router.push(options.pathAfterFailure || "/login");
      }
    }

    render() {
      const { loading } = this.state;

      if (loading) {
        return <div />;
      }

      return <Component {...this.props} />;
    }
  }

  return connect((state) => ({
    isLoggedIn: state?.authenticated && !!state?.user,
  }))(AuthenticatedRoute);
};

export default authenticatedRoute;

我們在這裡所做的重大更改是導入 206 215 中的方法 包(已經安裝在樣板文件中),然後調用該函數,將其傳遞給 228 函數,然後將它包裹在我們的組件周圍。明確一點,這部分:

/components/AuthenticatedRoute/index.js

return connect((state) => ({
  isLoggedIn: state?.authenticated && !!state?.user,
}))(AuthenticatedRoute);

在這裡,我們作為第一個參數傳遞給 238 的函數 是 241 函數(在 255 中命名 文檔)。此函數獲取 266 提供的應用程序的當前全局狀態 在 277 在 CheatCode Next.js 樣板中。

使用該狀態,顧名思義,它映射 該狀態將傳遞給我們的 289 的 React 組件道具 就在它上面定義的組件。

如果我們仔細看,在這裡,我們設置了一個名為 298 的道具 , 檢查是否 304 我們狀態的值是 317 以及我們是否有 321 對象狀態。如果我們這樣做?用戶已登錄!如果沒有,334 是假的。

如果你回頭看348 函數,這是我們放置新的 357 的地方 道具使用。

使用其他身份驗證源

如果你不是 使用 CheatCode Next.js 樣板,您如何獲得用戶的身份驗證狀態取決於您的應用程序。使用另一個 API 的快速而骯髒的示例如下所示:

import React from "react";
import Router from "next/router";
import { connect } from "react-redux";
import { myAuthenticationAPI } from 'my-authentication-api';

const authenticatedRoute = (Component = null, options = {}) => {
  class AuthenticatedRoute extends React.Component {
    state = {
      loading: true,
    };

    async componentDidMount() {
      const isLoggedIn = await myAuthenticationAPI.isLoggedIn();

      if (isLoggedIn) {
        this.setState({ loading: false });
      } else {
        Router.push(options.pathAfterFailure || "/login");
      }
    }

    render() {
      const { loading } = this.state;

      if (loading) {
        return <div />;
      }

      return <Component {...this.props} />;
    }
  }

  return AuthenticatedRoute;
};

export default authenticatedRoute;

在這個例子中,幾乎所有的東西都是一樣的,但是我們並沒有期待來自 Redux 存儲的認證值,而是直接調用我們的認證 API(例如 Firebase),依賴該調用的返回值作為我們的 365 狀態。

實現公共路由組件

現在,一些好消息:我們的 371 組件相同 與我們在上面看到的內容略有不同:

/components/PublicRoute/index.js

import React from "react";
import Router from "next/router";
import { connect } from "react-redux";

const publicRoute = (Component = null, options = {}) => {
  class PublicRoute extends React.Component {
    state = {
      loading: true,
    };

    componentDidMount() {
      if (!this.props.isLoggedIn) {
        this.setState({ loading: false });
      } else {
        Router.push(options.pathAfterFailure || "/documents");
      }
    }

    render() {
      const { loading } = this.state;

      if (loading) {
        return <div />;
      }

      return <Component {...this.props} />;
    }
  }

  return connect((state) => ({
    isLoggedIn: state?.authenticated && !!state?.user,
  }))(PublicRoute);
};

export default publicRoute;

你能發現嗎?在 383 中 我們添加了一個 393 說“如果用戶不是 登錄,繼續渲染組件。如果他們已登錄,請重定向他們。”

從字面上看,我們的 403 的逆邏輯 . 這裡是我們要使用的414 421 等路由上的組件 或 439 重定向已通過身份驗證的用戶離開 從那些頁面。這樣可以確保我們以後不會出現數據庫混亂,例如重複用戶或多個用戶會話。

總結

在本教程中,我們學習了一種創建 HOC(高階組件)的簡單模式,用於根據用戶的登錄(身份驗證)狀態在我們的應用程序中重定向用戶。我們學習瞭如何實現“包裹”在我們試圖保護的組件周圍的基本組件,以及如何實現處理渲染和重定向過程的核心邏輯。

我們還查看了使用實際身份驗證數據添加一些上下文並闡明此模式如何在任何中工作的示例 Next.js 中的身份驗證設置。


下一篇
No
Tutorial JavaScript 教程
  1. 如何將 Django 連接到 ReactJs

  2. 借用-ui:一個 React 組件庫啟動器

  3. JavaScript for of |示例代碼

  4. JavaScript 的這十年

  5. 如何在不離開頁面的情況下使用 django-allauth 登錄/註冊。

  6. 在您的下一個 Angular 應用程序中使用管道! (第1部分)

  7. Dynamics CRM 365 WebApi 8.2 AddListMembersList 方法

  1. HTML 樣式內聯性能:以及如何處理它

  2. 你可能錯過的關於 JSON 的一些事情

  3. 374. 猜數字高或低(javascript解決方案)

  4. 拖拽下載:從瀏覽器拖拽鏈接到桌面下載

  5. Angular 13 PDF 教程 – 使用 JSPDF 在 Angular 中導出 PDF

  6. 使用 Blazor JavaScript 互操作

  7. 如何在 JS 中獲取 Shoutcast 當前曲目的標題和插圖

  1. JavaScript 加載策略

  2. 對象和數組在 console.log() 中記錄了什麼?

  3. 使用 Node.js 創建一個 Hello Word 服務器

  4. 電子大冒險:第 41 集:馬爾科