Как сохранить или пополнить React Context на сайте Gatsby

Я использую React Context API для хранения информации о том, что пользователь аутентифицирован.

В режиме разработки, когда я ввожу любой URL-адрес, который перенаправляет на страницу ошибки 404, данные контекста теряются. Когда я перехожу на действительную страницу, ранее вошедший в систему пользователь больше не входит в систему.

Обновлено: Я только что проверил это с gatsby build и gatsby serve. Встроенный 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>
  );
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
7
0
2 087
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

Если вы еще не реализовали свой уровень аутентификации, вам нужно посмотреть, как это будет работать. Существует ряд стратегий для поддержания этого состояния, даже при использовании хранилища на основе файлов cookie. JWT (веб-токен JSON) — это популярный метод, который позволит вам хранить подписанные данные пользователя и данные, доступные для чтения клиентом, в файле 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 в файле cookie session при монтировании AuthContextProvider и обновит состояние значением userid, хранящимся в JWT, если оно присутствует.

Вероятно, вы захотите обернуть Гэтсби App этим компонентом, что вы можете сделать из файлов gatsby-browser.js и 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 в соответствующий момент в жизненный цикл вашего приложения.

Я надеюсь, что это поможет вам или другим. В сообщении блога ниже описывается, как использовать gatsby-browser.js для переноса корневого элемента в провайдер, чтобы он не сбрасывал его при изменении страницы.

https://www.gatsbyjs.org/blog/2019-01-31-using-react-context-api-with-gatsby/

У вас есть 3 возможности:

  1. веб-хранилище, также известное как localStorage или sessionStorage (самое простое, наименее безопасное)
  2. сеансовые файлы cookie (безопасные, требуется внутренний сервер)
  3. веб-токены json (JWT) (наиболее безопасные, требуется внутренний сервер)

Отличное чтение о справочной информации — этот блог на dev.to.

1. веб-хранилище, такое как localStorage

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

Этот вопрос описывает, как его использовать:

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.info('retrievedObject: ', JSON.parse(retrievedObject));

2. куки-файлы или сеансовые куки-файлы

Для Express вы можете использовать express-ession. Другие веб-серверы имеют аналогичное промежуточное ПО. Суть в том, чтобы предоставить информацию о пользователе в файле cookie, как описано в МДН.

3. веб-токены json

Это похоже на файлы cookie, но использует веб-токены JSON. @coreyward дал отличный ответ. Вы также можете прочитать больше в этот пост в блоге.

Другие вопросы по теме