如何在 Gatsby 站点中保留或重新提供 React Context
How to keep or resupply React Context in a Gatsby site
我使用 React Context API 来存储用户已通过身份验证的信息。
在开发模式下,当我输入任何重定向到 404 错误页面的 URL 时,上下文数据都会丢失。当我导航到一个有效页面时,以前登录的用户不再登录。
编辑: 我刚刚用 gatsby build 和 gatsby serve 测试了这个。构建的 gatsby 站点在重定向到 404 错误页面时会保留上下文。但是当导航到完全不同的 URL 例如 www.google.com.
时上下文仍然丢失
现在我的问题是:如何在不让用户再次手动登录的情况下为上下文重新提供登录信息?
这是我的 AuthContextProvider 包装器 class:
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 是关于向一个或多个子组件提供一些数据,而不必通过中间组件向下传递数据。没有 built-in 机制可以在页面加载之间保持状态,因此您需要为此使用其他工具。
如果您还没有实现身份验证层,您将需要了解它的工作原理。有许多策略可以维持该状态,即使只是在使用 cookie-based 存储时也是如此。 JWT(JSON Web 令牌)是一种流行的方法,它可以让您在 cookie 中存储签名用户和 client-readable 数据,但代价是需要更多的工作来管理 expiration/renewal 并拥有一个更大的有效载荷。假设这是您采用的方法,您可能会这样做:
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>
);
}
}
这将在安装 AuthContextProvider 时解析 session
cookie 中的 JWT 令牌,并使用存储在 JWT 中的 userid
值更新状态(如果存在)。
你可能想用这个组件包装 Gatsby App
,你可以从 gatsby-browser.js
和 gatsby-ssr.js
文件中完成(如果你在你的 repo 的根目录中创建它们还没有):
// 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 的创建在您的应用程序生命周期的相关点。
希望对您或其他人有所帮助。下面的博客 post 描述了您需要如何使用 gatsby-browser.js 将根元素包装在提供程序中,以便它不会在页面更改时重置它。
https://www.gatsbyjs.org/blog/2019-01-31-using-react-context-api-with-gatsby/
你有 3 种可能性:
- 网络存储又名 localStorage 或 sessionStorage(最简单,最不安全)
- 会话 cookie(安全,需要后端服务器)
- json 网络令牌 (JWT)(最安全,需要后端服务器)
有关背景信息的优秀读物是 this blog on dev.to。
1。网络存储,例如 localStorage
这被认为是最不安全的选项安全选项。不要在此处保存电子邮件地址等个人数据。永远不要保存敏感信息,例如信用卡信息等。
This question介绍使用方法:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');
console.log('retrievedObject: ', JSON.parse(retrievedObject));
2。 cookie 或会话 cookie
对于快递,您可以使用 express-ession
. Other web servers have similar middleware. The point is to supply the user info within a cookie as described on MDN。
3。 json 网络令牌
这类似于 cookie,但使用 JSON 网络令牌。 @coreyward 给出了很好的答案。您还可以在 this blog post.
中阅读更多内容
我使用 React Context API 来存储用户已通过身份验证的信息。
在开发模式下,当我输入任何重定向到 404 错误页面的 URL 时,上下文数据都会丢失。当我导航到一个有效页面时,以前登录的用户不再登录。
编辑: 我刚刚用 gatsby build 和 gatsby serve 测试了这个。构建的 gatsby 站点在重定向到 404 错误页面时会保留上下文。但是当导航到完全不同的 URL 例如 www.google.com.
时上下文仍然丢失现在我的问题是:如何在不让用户再次手动登录的情况下为上下文重新提供登录信息?
这是我的 AuthContextProvider 包装器 class:
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 是关于向一个或多个子组件提供一些数据,而不必通过中间组件向下传递数据。没有 built-in 机制可以在页面加载之间保持状态,因此您需要为此使用其他工具。
如果您还没有实现身份验证层,您将需要了解它的工作原理。有许多策略可以维持该状态,即使只是在使用 cookie-based 存储时也是如此。 JWT(JSON Web 令牌)是一种流行的方法,它可以让您在 cookie 中存储签名用户和 client-readable 数据,但代价是需要更多的工作来管理 expiration/renewal 并拥有一个更大的有效载荷。假设这是您采用的方法,您可能会这样做:
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>
);
}
}
这将在安装 AuthContextProvider 时解析 session
cookie 中的 JWT 令牌,并使用存储在 JWT 中的 userid
值更新状态(如果存在)。
你可能想用这个组件包装 Gatsby App
,你可以从 gatsby-browser.js
和 gatsby-ssr.js
文件中完成(如果你在你的 repo 的根目录中创建它们还没有):
// 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 的创建在您的应用程序生命周期的相关点。
希望对您或其他人有所帮助。下面的博客 post 描述了您需要如何使用 gatsby-browser.js 将根元素包装在提供程序中,以便它不会在页面更改时重置它。
https://www.gatsbyjs.org/blog/2019-01-31-using-react-context-api-with-gatsby/
你有 3 种可能性:
- 网络存储又名 localStorage 或 sessionStorage(最简单,最不安全)
- 会话 cookie(安全,需要后端服务器)
- json 网络令牌 (JWT)(最安全,需要后端服务器)
有关背景信息的优秀读物是 this blog on dev.to。
1。网络存储,例如 localStorage
这被认为是最不安全的选项安全选项。不要在此处保存电子邮件地址等个人数据。永远不要保存敏感信息,例如信用卡信息等。
This question介绍使用方法:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');
console.log('retrievedObject: ', JSON.parse(retrievedObject));
2。 cookie 或会话 cookie
对于快递,您可以使用 express-ession
. Other web servers have similar middleware. The point is to supply the user info within a cookie as described on MDN。
3。 json 网络令牌
这类似于 cookie,但使用 JSON 网络令牌。 @coreyward 给出了很好的答案。您还可以在 this blog post.
中阅读更多内容