react-atom icon indicating copy to clipboard operation
react-atom copied to clipboard

Bootstrapping an Atom from localStorage... how to?

Open gremo opened this issue 5 years ago • 0 comments

I'm new to React and this library, so my question may be a bit silly.

I'm using React hooks like useState, useReducer and dispatch inside components and using custom helper functions. For a small app like mine, this is overkill.

I need to persist the state into the local storage, but I don't know to do this using this library. Using React state management, I would use a custom hook like this:

import React from 'react';

/**
 * @param {string} storageKey
 * @param {*} initialState
 * @param {number} expiration
 */
export const useStateWithLocalStorage = (storageKey, initialState, expiration) => {
  const [value, setValue] = React.useState(() => {
    const value = localStorage.getItem(storageKey);
    if (null === value || 'undefined' === typeof value) {
      return initialState;
    }

    const expiration = parseInt(localStorage.getItem(`${storageKey}_expire`));
    if (!isNaN(expiration) && Math.floor(Date.now() / 1000) > expiration) {
      localStorage.removeItem(`${storageKey}_expire`);

      return initialState;
    }

    if ('{' === value[0] || '[' === value[0]) {
      return JSON.parse(value);
    }

    return value;
  });

  React.useEffect(() => {
    localStorage.setItem(storageKey, null !== value && 'object' === typeof value ? JSON.stringify(value) : value);

    if (expiration > 0) {
      const existingExpiration = localStorage.getItem(`${storageKey}_expire`);
      if (null === existingExpiration || 'undefined' === typeof existingExpiration) {
        localStorage.setItem(`${storageKey}_expire`, Math.floor(Date.now() / 1000) + expiration);
      }
    }
  }, [storageKey, value, expiration]);

  return [value, setValue];
};

gremo avatar Sep 16 '20 13:09 gremo