Как сохранить или пополнить контекст React на сайте Gatsby - PullRequest
3 голосов
/ 03 июля 2019

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

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

Я никогда раньше не работал с React Context, поэтому я не уверен, что с этим делать. Это намеренное поведение? Есть ли способы сохранить специфичный для пользователя контекст React? Нужно ли пополнять контекст из бэкэнда? Или я просто ошибся? Какой лучший курс действий?

Я бы хотел как-то сохранить контекст в браузере до истечения времени сеанса. Обработка сеансов из бэкэнда еще не реализована.

РЕДАКТИРОВАТЬ: Я только что проверил это с gatsby build и gatsby serve. Встроенный сайт Гэтсби сохраняет контекст при перенаправлении на страницу ошибки 404. Но контекст все еще теряется при переходе на совершенно другой URL, такой как www.google.com.

Теперь мой вопрос: как мне пополнить контекст с информацией для входа в систему без повторного входа пользователя вручную? Проверка cookie? Извините, если я задаю очевидный вопрос. Я никогда не использовал сессии или куки.

Вот мой класс оболочки AuthContextProvider:

import React from "react";

export const AuthContext = React.createContext();

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

  render() {
    return (
      <AuthContext.Provider
        value={{
          authenticated: this.state.authenticated,
          userid: this.state.userid,
          toggleLogin: () => {
            const previousValueState = this.state.authenticated;
            this.setState(state => ({
              authenticated: !previousValueState,
              userid: 2,
            }));
          },
        }}
      >
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

Я обертываю все свое приложение с поставщиком контекста в корневой макет:

export default function RootLayout({ children }) {
  return (
    <React.Fragment>
      <Helmet>
        <meta
          name="viewport"
          content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
        />
        <link rel="stylesheet"
              href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600&display=swap" />
      </Helmet>
      <GoogleReCaptchaProvider reCaptchaKey={recaptchaSiteKey}>
        <ThemeProvider theme={theme}>
          <CssBaseline />
          <AuthContextProvider>
            {children}
          </AuthContextProvider>
        </ThemeProvider>
      </GoogleReCaptchaProvider>
    </React.Fragment>
  );
}

1 Ответ

1 голос
/ 10 июля 2019

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

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

Возможно, вы захотите обернуть Gatsby 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 в соответствующий момент в жизненном цикле вашего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...