Skip to content

Instantly share code, notes, and snippets.

@coreyward
Last active November 7, 2021 09:39
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coreyward/668ab5d84758001ed55da8511da08505 to your computer and use it in GitHub Desktop.
Save coreyward/668ab5d84758001ed55da8511da08505 to your computer and use it in GitHub Desktop.
I wrote this hook to persist a simple user settings (think dark mode) to local storage in a cross-tab compatible way.

useStorage React Hook

Similar to useState but with some lightweight behind-the-scenes writing to localStorage; also subscribes to changes in localStorage to allow for cross-tab changes to sync automatically.

Example Usage

The first argument is the name of the local storage property/key you want to control with this hook. The second argument, options, really just has one available directive: bool. Setting bool to true has the effect of evaluating the data returned from getItem as a boolean (otherwise it's always a string).

import useStorage from "./useLocalStorage.js"

const App = () => {
  const [darkMode, setDarkMode] = useStorage("dark-mode", { bool: true })
  
  return (
    <div
      style={{
        background: darkMode ? "#333" : "#eee",
        color: darkMode ? "#bbb" : "#333",
      }}
    >
      Hello, world!
    </div>
  )
}

export default App
import { useState, useCallback, useEffect } from "react"
// Similar to `useState` but with some lightweight behind-the-scenes
// writing to localStorage; also subscribes to changes in localStorage
// to allow for cross-tab changes to sync automatically.
const useStorage = (key, { bool }) => {
const [value, setValue] = useState()
useEffect(() => {
const rawValue = window.localStorage.getItem(key)
setValue(bool ? parseRawValue(rawValue) : rawValue)
const handleChanges = e => {
if (e.key === key) {
setValue(bool ? parseRawValue(e.newValue) : e.newValue)
}
}
window.addEventListener("storage", handleChanges)
return () => {
window.removeEventListener("storage", handleChanges)
}
}, [key, bool])
const updater = useCallback(
newValue => {
setValue(newValue)
window.localStorage.setItem(key, newValue)
},
[key]
)
return [value, updater]
}
export default useStorage
const parseRawValue = rawValue =>
rawValue === "true" || rawValue === "1"
? true
: rawValue === "false" || rawValue === "0"
? false
: rawValue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment