如何在 Gatsby 站点中保留或重新提供 React Context

2023-11-23

我使用 React Context API 来存储用户经过身份验证的信息。

在开发模式下,当我输入任何重定向到 404 错误页面的 URL 时,上下文数据都会丢失。当我导航到有效页面时,先前登录的用户将不再登录。

EDIT:我刚刚使用 gatsby build 和 gatsbyserve 对此进行了测试。构建的 gatsby 站点在重定向到 404 错误页面时会保留上下文。但当导航到完全不同的 URL 时,上下文仍然会丢失,例如www.google.com.

现在我的问题是:如何在不让用户再次手动登录的情况下重新提供上下文与登录信息?

这是我的 AuthContextProvider 包装类:

export class AuthContextProvider extends React.Component {
  constructor(props) {
    super(props);
    this.state = { user: {} };
  }
  
  // ...
  
  render() {
    return (
      <AuthContext.Provider value={{ getUser: this.getUser, setUser: this.setUser }}>
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}  

我将整个应用程序与上下文提供程序包装在根布局中:

const RootLayout = ({ children }) => {
  return (
    <AuthContextProvider>
      {children}
    </AuthContextProvider>
  );
}

React Context 旨在向一个或多个子组件提供一些数据,而无需通过中间组件向下传递数据。没有内置机制可以在页面加载之间保留状态,因此您需要使用另一个工具来实现这一点。

如果您尚未实现身份验证层,您将需要了解其工作原理。有许多策略可以维持该状态,即使只是使用基于 cookie 的存储也是如此。 JWT(JSON Web 令牌)是一种流行的方法,它允许您在 cookie 中存储签名的用户和客户端可读数据,但需要更多的工作来管理过期/续订并具有更大的有效负载。假设这就是您采取的方法,您可能会这样做:

import React from "react";
import jwt from "jsonwebtoken"; // Add jsonwebtoken via npm/yarn

function getCookieValue(a) {
  var b = document.cookie.match('(^|[^;]+)\\s*' + a + '\\s*=\\s*([^;]+)');
  return b ? b.pop() : '';
}

const AUTH_PUBLIC_KEY = "your JWT public key here"

export const AuthContext = React.createContext();

export class AuthContextProvider extends React.Component {
  state = {
    authenticated: false,
    userid: null,
  };

  componentDidMount() {
    jwt.verify(getCookieValue("session"), AUTH_PUBLIC_KEY, (err, session) => {
      if (!err && session.userid) {
        this.setState({ userid: session.userid, authenticated: true })
      }
    })
  }

  // Important: REMOVE THIS AFTER TESTING/DEV
  toggleLogin = () => {
    this.setState(state => ({
      authenticated: !state.authenticated,
      userid: 2,
    }));
  }

  render() {
    return (
      <AuthContext.Provider
        value={{
          ...this.state,
          toggleLogin: this.toggleLogin,
        }}
      >
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

这将解析 JWT 令牌session加载 AuthContextProvider 时的 cookie 并使用 更新状态userid存储在 JWT 中的值(如果存在)。

你可能想把盖茨比包装起来App使用此组件,您可以从gatsby-browser.js and gatsby-ssr.js文件(如果您还没有的话,请在存储库的根目录中创建它们):

// gatsby-browser.js
import React from "react"
import AuthContextProvider from "components/AuthContextProvider"

export const wrapRootElement = ({ element }) =>
  <AuthContextProvider>{element}</AuthContextProvider>

// gatsby-ssr.js
import React from "react"
export { wrapRootElement } from "./gatsby-browser"

您仍然需要处理生成 JWT 令牌(可能来自处理身份验证的后端),如果它尚未保存在 cookie 中,您可以从浏览器访问,您将需要在相关点处理该 cookie 的创建您的应用程序生命周期。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Gatsby 站点中保留或重新提供 React Context 的相关文章

随机推荐

  • 使用 jquery 禁用输入 type="image" 的正确方法是什么?

    使用 jQuery 我尝试禁用这样的输入字段
  • 从两个字符串中获取编辑

    我将深入探讨我的问题 如果您不想阅读所有内容 可以跳至 TL DR 我正在尝试做什么 我需要存储一个 文件 文本文件 可以由用户编辑 如果我有原始文件 这可能是巨大的 Lorem ipsum dolor 坐 amet 用户要进行更改 Foo
  • 收集多组列

    我从一项在线调查中获得了数据 其中受访者回答了 1 3 次问题 调查软件 Qualtrics 将这些数据记录在多个列中 即调查中的 Q3 2 将包含列Q3 2 1 Q3 2 2 and Q3 2 3 df lt data frame id
  • 文本视图中的触摸坐标

    我在文本视图上使用触摸监听器 我可以通过运动事件获取触摸坐标 我可以获取我单击的字符索引或附近的字符坐标吗 Eg Hello Android 这是我的文字 现在我可以获得 x y 坐标 但是我可以获得字符索引吗 A 当我触摸它时 您必须重写
  • Rails 3.1 资产在生产中没有指纹

    刚开始适应rails 3 1 我开始编写coffeescript和sass 开发中一切正常 当我在生产中运行服务器时 我只得到 在页面的源代码中 没有生成哈希码 并且两个资产都有路由错误 Routing Error No route mat
  • C中“==”运算符的返回值

    我是否可以假设在 C 中 如果两个值相等 运算符将始终计算为 1 或者它可以计算为其他 真 值 struct ss int id struct os int sid int state int count struct ss s int s
  • 使用 ABAP 7.40+ 语法进行最有效的 itab 过滤

    在 7 40 版本中 我们有很多方法来过滤内部表数据 例如 可以使用这样的 ABAP 结构 FILTER操作员 DATA lt extract FILTER lt bseg USING KEY matnr bwtar WHERE matnr
  • 如何在node.js中保存.env文件中的更改

    I use dotenv用于读取环境变量 像这样 let dotenv require dotenv config path env console log process env DB HOST 现在我想保存更改 env文件 我找不到任何
  • 什么是非线性模式

    我正在阅读有关servant api DSL 参见 pdfhere 引用自第 5 2 节 类型安全链接 强调是我添加的 type family ElSymbol e s Symbol a Bool where ElSymbol s gt e
  • 如何使用自定义的类文件对象作为子进程 stdout/stderr?

    考虑这段代码 其中subprocess Popen被催生 我想写入子进程 stdout and stderr转到我的自定义文件对象 write 方法 但事实并非如此 import subprocess class Printer def i
  • PL/pgSQL 匿名代码块

    在 PostgreSQL 9 0 中 我有这个 PLPGSQL 匿名代码块 DO DECLARE bigobject integer BEGIN SELECT lo creat 1 INTO bigobject ALTER LARGE OB
  • Android任务亲和性的使用

    我正在阅读有关任务亲和性的内容并创建了一个具有以下活动的演示应用程序 A B gt 任务亲和力 com ando C D gt 任务亲和力 com ando E 据说 具有相同任务亲和性的活动会秘密打开另一个活动的单个实例 因此 我在每个活
  • Android 深色模式:夜间值不起作用

    我正在我的应用程序中开发日 夜功能 因此我阅读了这些文档并开始开发它 它在白天或夜间的默认值下工作正常 用精细方法AppCompatDelegate setDefaultNightMode 用于定制night我创建的主题颜色价值观之夜文件夹
  • java中如何找出谁创建了线程?

    在tomcat中 如果web应用程序确实停止了非守护线程 则tomcat无法通过shutdown sh关闭 例如 public class demo implements ServletContextListener public void
  • NSTextAlignment 对齐到 UILabel 文本对齐在 iOS6 上会崩溃

    我现在使用Xcode 4 5和iOS6 iOS6改变了UILabel文本对齐方式 label textAlignment NSTextAlignmentJustified 该代码将在带有 ios6 SDK 的 iPhone 6 0 模拟器上
  • 的证书与任何主题备用名称都不匹配

    错误 javax net ssl SSLException Certificate for
  • 是否有一种[直接]方法可以使用 SQL 对结果*first*、*then*按另一列进行分组?

    我看到在 SQL 查询中 GROUP BY子句必须先于ORDER BY 这是否意味着在分组之后完成排序会丢弃相同的行 因为我似乎需要首先按时间戳对行进行排序 then丢弃具有相同时间戳的行 我不知道如何实现这一点 我正在使用 MySQL 5
  • 需要帮助来理解带有 /d 的 perl tr 命令

    我在网上发现了以下 Perl 示例 usr bin perl string the cat sat on the mat string tr a z b d print string n result b b b 有人可以解释一下吗 d表示
  • 如何按需运行后台服务 - 而不是在应用程序启动时或在计时器上运行

    在 Net 5 Web API 中 我想运行一个发送批量电子邮件和短信的后台任务 我知道我可以创建一个继承自BackgroundService的服务 然后将其添加到Startup ConfigureServices方法中的DI容器中 如下所
  • 如何在 Gatsby 站点中保留或重新提供 React Context

    我使用 React Context API 来存储用户经过身份验证的信息 在开发模式下 当我输入任何重定向到 404 错误页面的 URL 时 上下文数据都会丢失 当我导航到有效页面时 先前登录的用户将不再登录 EDIT 我刚刚使用 gats