How to keep or resupply React Context in a Gatsby site

后端 未结 3 1510
小鲜肉
小鲜肉 2021-01-02 18:06

I use React Context API to store the information that a user is authenticated.

In development mode when I type in any URL that redirects to the 404 error page the con

3条回答
  •  一向
    一向 (楼主)
    2021-01-02 18:58

    React Context is about providing some data to one or more child components without having to pass the data down through intermediary components. There's no built-in mechanism for persisting state between page loads, so you'll need to reach for another tool for that.

    If you haven't already implemented your authentication layer, you'll want to look into how that will work. There are a number of strategies for maintaining that state, even just within using cookie-based storage. JWT (JSON Web Token) are a popular method that will let you store signed user and client-readable data in the cookie at the cost of requiring a bit more work to manage expiration/renewal and having a larger payload. Assuming that's the approach you took, you might do something like this:

    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 (
          
            {this.props.children}
          
        );
      }
    }
    

    This will parse the JWT token in the session cookie when the AuthContextProvider is mounted and update the state with the userid value stored in the JWT if one is present.

    You will probably want to wrap the Gatsby App with this component, which you can do from gatsby-browser.js and gatsby-ssr.js files (create them in the root of your repo if you don't have them yet):

    // gatsby-browser.js
    import React from "react"
    import AuthContextProvider from "components/AuthContextProvider"
    
    export const wrapRootElement = ({ element }) =>
      {element}
    
    
    // gatsby-ssr.js
    import React from "react"
    export { wrapRootElement } from "./gatsby-browser"
    

    You will still need to handle generating the JWT token (probably from a backend that is handling authentication) and if it's not already being persisted in a cookie you can access from the browser you will need to handle creation of that cookie at the relevant point in your application lifecycle.

提交回复
热议问题