Logo

dev-resources.site

for different kinds of informations.

How to Make localStorage Data Reactive

Published at
12/9/2024
Categories
localstorage
react
webdev
Author
rain9
Categories
3 categories in total
localstorage
open
react
open
webdev
open
Author
5 person written this
rain9
open
How to Make localStorage Data Reactive

Major Update

📣 Exciting News Alert! Don't miss out!

INFINI Labs is dedicated to providing high-quality open-source tools to developers and enterprises, continuously enhancing the vibrancy of the tech ecosystem. Along with maintaining popular projects like the analysis-ik and analysis-pinyin plugins, we are actively driving the release of more top-tier open-source products.

To celebrate Infini Tech’s third anniversary, the following products and tools are now fully open-source:

  • INFINI Framework
  • INFINI Gateway
  • INFINI Console
  • INFINI Agent
  • INFINI Loadgen
  • INFINI Coco AI

All these open-source projects are available on GitHub: https://github.com/infinilabs

We’d greatly appreciate your Star🌟 to support us!

Background

While developing the company's project INFINI Cloud (not yet open-source, stay tuned!), there was a global timezone adjustment component and a local timezone adjustment component. The goal was to have them synchronize and respond in real-time when timezone changes occurred.

Image description

Tip: If you're interested in this time component, feel free to visit https://github.com/infinilabs/ui-common. We’d love your Star🌟 and collaboration.

The timezone data was stored in the frontend's localStorage, and the time component fetched its default value from there. However, if the current page wasn’t refreshed, the time component couldn't update to the latest localStorage data.

How can we make localStorage reactive?

Implementation

  1. Create a reusable method, applicable to timezone and other data in the future.
  2. As the project is React-based, write a custom hook.
  3. To make localStorage reactive, should we rely on listeners?

Failed Attempt 1

Initially, the idea was to approach it as follows:

useEffect(() => { 
    console.log(11111, localStorage.getItem('timezone')); 
}, [localStorage.getItem('timezone')]);
Enter fullscreen mode Exit fullscreen mode

This approach failed. Why? Research indicates that using localStorage.getItem('timezone') as a dependency causes recalculations on every render, which is incorrect.

For details, refer to the official React documentation on useEffect(setup, dependencies?).

Failed Attempt 2

The next idea was to use window's storage event to listen for changes:

// useRefreshLocalStorage.js
import { useState, useEffect } from 'react';

const useRefreshLocalStorage = (key) => {
  const [storageValue, setStorageValue] = useState(
    localStorage.getItem(key)
  );

  useEffect(() => {
    const handleStorageChange = (event) => {
      if (event.key === key) {
        setStorageValue(event.newValue);
      }
    };

    window.addEventListener('storage', handleStorageChange);

    return () => {
      window.removeEventListener('storage', handleStorageChange);
    };
  }, [key]);

  return [storageValue];
};

export default useRefreshLocalStorage;
Enter fullscreen mode Exit fullscreen mode

Testing showed no effect because the storage event only listens for changes across different pages of the same origin, not changes within the same page.

Successful Approach

The solution involves creating a custom event:

import { useState, useEffect } from "react";

function useRefreshLocalStorage(localStorage_key) {
  if (!localStorage_key || typeof localStorage_key !== "string") {
    return [null];
  }

  const [storageValue, setStorageValue] = useState(
    localStorage.getItem(localStorage_key)
  );

  useEffect(() => {
    const originalSetItem = localStorage.setItem;
    localStorage.setItem = function (key, newValue) {
      const setItemEvent = new CustomEvent("setItemEvent", {
        detail: { key, newValue },
      });
      window.dispatchEvent(setItemEvent);
      originalSetItem.apply(this, [key, newValue]);
    };

    const handleSetItemEvent = (event) => {
      if (event.detail.key === localStorage_key) {
        setStorageValue(event.detail.newValue);
      }
    };

    window.addEventListener("setItemEvent", handleSetItemEvent);

    return () => {
      window.removeEventListener("setItemEvent", handleSetItemEvent);
      localStorage.setItem = originalSetItem;
    };
  }, [localStorage_key]);

  return [storageValue];
}

export default useRefreshLocalStorage;
Enter fullscreen mode Exit fullscreen mode

Integration and Testing

Encapsulate timezone logic in a hook:

// useTimezone.js
import { useState, useEffect } from "react";
import { getTimezone, timezoneKey } from "@/utils/utils";
import useRefreshLocalStorage from "./useRefreshLocalStorage";

function useTimezone() {
  const [TimeZone, setTimeZone] = useState(() => getTimezone());
  const [storageValue] = useRefreshLocalStorage(timezoneKey);

  useEffect(() => {
    setTimeZone(() => getTimezone());
  }, [storageValue]);

  return [TimeZone];
}

export default useTimezone;
Enter fullscreen mode Exit fullscreen mode

Use it in your component:

import useTimezone from "@/hooks/useTimezone";

export default (props) => {
  const [TimeZone] = useTimezone();

  useEffect(() => { 
    console.log(11111, TimeZone); 
  }, [TimeZone]);
};
Enter fullscreen mode Exit fullscreen mode

The tests were successful!

Conclusion

While a global store or state management solution could achieve similar results, this implementation leverages localStorage for historical reasons.

Have better ideas? Let’s discuss!

localstorage Article's
30 articles in total
Favicon
É seguro guardar dados do usuário no localStorage?
Favicon
Understanding Local Storage and Session Storage in JavaScript
Favicon
How to Make localStorage Data Reactive
Favicon
Enhance React Native Security and Performance: with MMKV Storage
Favicon
# Storing Data in the Database with JavaScript
Favicon
Efficient Data Management in Manufacturing: Leveraging localStorage in Angular
Favicon
Beginner's Guide to Web Scraping and Proxy Setup with JavaScript
Favicon
Securing Web Storage: LocalStorage and SessionStorage Best Practices
Favicon
Javascript Ls/ss/cookies
Favicon
Javascript Ls/ss/cookies
Favicon
Javascript Ls/ss/cookies😎
Favicon
Faking sessionStorage to keep sites from crashing
Favicon
Elevating Data Integrity in Your React Application with Converters in Storage Management
Favicon
Storing and Testing State in localStorage with React
Favicon
Local Storage in 5 mins: A Beginner’s Guide to Cookies, localStorage, and sessionStorage
Favicon
Mastering LocalStorage Management with React Hooks
Favicon
Utilizing Local Storage in React Components: A Comprehensive Guide
Favicon
Working with JavaScript Local Storage
Favicon
LocalStorage with React Hooks
Favicon
Learn Local Storage in React: Create a Light and Dark Theme Switcher Application
Favicon
Lokalnotes - onBrowser notesapp
Favicon
Local Storage vs Session Storage in JavaScript
Favicon
Cookies vs Local Storage vs Session Storage
Favicon
How to show a pop-up only once with React, localStorage and Material UI modal
Favicon
Local Storage Bookmark Manager
Favicon
Mongez Cache, a powerful storage manager for web applications
Favicon
Using the Local Storage API in React: Creating a custom hook component
Favicon
-
Favicon
彻底弄清楚session,cookie,sessionStorage,localStorage的区别及应用场景(面试向)
Favicon
Must have Custom hooks for NextJs

Featured ones: