Explaining localStorage and Provider/ Context with example

Hi guys!

This is more for beginners developers and I decided to write this article as I came across many times with a task to create a local storage state and then use a Provider for different type of features on an application. Thought to share and hopefully it will be more understandable so you can use the concept anywhere.

Lets work through an example:

Let's say we create a text where the initial state is visible and once we click the text disappears, however is stored in memory. Normally with useState the state of that handler changes but is not persistent once the page re-renders.

In that case we will use localstorage since we manage the state internally in our applciation. For localStorage I found some react-hooks that are really good
Check here

I am gonna be using TypeScript for our code.
Based on that example the first step is to import our package and start creating the initial or default state of that text(visible-invisible) with the types. For the state we create the context and we import from react another hook as well called useContext.

Let's create a file name TextVisibleProvider.tsx

import React, { useContext, ReactNode } from 'react'
import useLocalStorageState from 'use-local-storage-state'

type TextContextType = {
  isTextVisible: boolean
  setTextVisible: () => void
}

const TextContext = React.createContext<TextContextType>({
  isTextVisible: false,
  setTextVisible: () => {
    console.log('is text visible')
  },
})

export const useTextVisible = () => useContext(TextContext)

Then we create our Provider. The provider is important cause it what is gonna hold our localstorage in memory across the application which is also important to put it on top level component as a wrapper. Below the useLocalStorageState replaces the useState hook. We have a key text-storage and the initial state which is false. Inside the provider you can create any function that will change the state in that case the handleTextVisibility.

const TextProvider = ({ children }: { children: ReactNode }) => {
  const [isTextVisible, setTextVisible] = useLocalStorageState(
    'text-storage',
    false,
  )

  const handleTextVisibility = () => {
    if (!isTextVisible) {
      setTextVisible(true)
    }
  }

  return (
    <TextContext.Provider
      value={{ setTextVisible: handleTextVisibility, isTextVisible }}
    >
      {children}
    </TextContext.Provider>
  )
}

export default TextProvider

Now le'ts create a small component that has the text and a button that manages the state. As you can see you are exporting the state inside the TextProvider so that you can use it anywhere in your project.

Create a TextVisible.tsx

const TextVisible = (): JSX.Element => {
  const { isTextVisible, setTextVisible } = useTextVisible()

  return (
    <div>
      {!isTextVisible && (
        <div>
            <p>
              This website is using cookies to enhance the user experience.
            </p>
            <button
              onClick={() => setTextVisible()}
            >
              I accept
            </button>
        </div>
      )}
    </div>
  )
}

export default TextVisible

Then you put the TextProvider on level higher than the component that we just made or it could be on an index file.

15