Gatsby: Using localStorage to store data

Viewed 3714

I have a Gatsby site and I'm implementing a GDPR consent banner. I want to store state in local storage containing a "true" or "false" string pertaining to if the user has accepted the GDPR terms.

For example, a user shows up to the site for the first time. In local storage there is a "GDPR_Accepted" key that is set to "false". If the user doesn't accept the GDPR terms on the home page the banner will continue to be displayed on every page the user visits. When the user clicks accept the GDPR_Accepted value is set to "true", and a ternary operator in my React component applies a CSS class that hides the banner.

Because I'm using local storage the "true" value should persist even if the user leaves the page and returns later (assuming they don't clear their browsing history). The problem is with Gatsby. Gatsby uses server side rendering and when the user accepts the GDPR terms and leaves the website and comes back, the GDPR value is reset to "false". Gatsby is unable to persist the local storage data from earlier when it was set to "true".

How can I persist data in local storage in a Gatsby project? Would it make more sense to just use React state to store whether or not the user has accepted the GDPR terms?

1 Answers

I've built a full working example just to confirm that this works. Just run gatsby build and then gatsby serve to see how it should run after it's built.

/* src/pages/index.js */

import React, {useState, useEffect} from 'react'

const IndexPage = () => {
  const [agreed, setAgreed] = useState(false)

  // This runs when the page is loaded.
  useEffect(() => {
    if (localStorage.getItem('agree')) {
      setAgreed(true)
    }
  }, [])

  const handleClick = () => {
    localStorage.setItem('agree', 'true')
    setAgreed(true)
  }

  const AgreeButton = <button onClick={handleClick}>Click me to agree</button>

  return (
    <>
      <h1>Welcome to my page!</h1>
      {agreed
        ? <p>You agreed!</p>
        : AgreeButton
      }
    </>
  )
}

export default IndexPage

I think maybe you are misunderstanding how Gatsby works. With something like Create React App, the server sends a pretty bare bones HTML document with a single <root> element in the body. With Gatsby, the pages are constructed at build time. This helps a ton with performance because the user's browser doesn't have to completely build the page from scratch.

Maybe you are thinking that because of this, you can't do a lot of the stuff that you can do with Create React App because it boils everything down to HTML before it reaches the user. That's not the case. You can still use hooks and state and all that fun stuff thanks to React Hydration. From the Gatsby docs:

the browser can “pick up” where the server left off with the contents created by Gatsby in the /public folder and render the site in the browser like any other React app would.

Related