Untitled

 avatar
unknown
tsx
2 years ago
1.6 kB
2
Indexable
import { useState, useEffect } from 'react';
import CryptoJS from 'crypto-js';
import { useRouter } from 'next/router';

function useLocalStorage<T>(
  key: 'userAuth' | 'buyCartItems' | 'test',
  initialValue: any,
): [T, (value: T) => void] {
  // protect-key for encrypt and decrypt local-storage
  const protectKey = 'Z>rp1p+~u';

  // local-storage state status : undefined (loading before set local-storage data), initialValue (initial value and not found key in local storage), data
  const [state, setState] = useState<any>(undefined);

  // if change route update customHook state
  // if(key in local-storage) ? set-state(decrypted key-value) : set-state(initialValue)
  // if edited local-storage ===> remove key from local storage ===> re-render useEffect [key is dependencies] ===> not found key in local storage and set-state(initialValue)
  const router = useRouter();
  const { asPath } = router;
  
  useEffect(() => {
    const item = localStorage.getItem(key);
    if (item) {
      try {
        const decryptState = CryptoJS.AES.decrypt(item, protectKey).toString(
          CryptoJS.enc.Utf8,
        );
        setState(JSON.parse(decryptState));
      } catch {
        localStorage.removeItem(key);
      }
    } else {
      setState(initialValue);
    }
  }, [asPath, key]);

  // encrypt and set-data to local-storage
  const setStateHandler = (value: T) => {
    const encryptedState = CryptoJS.AES.encrypt(
      JSON.stringify(value),
      protectKey,
    );
    localStorage.setItem(key, encryptedState.toString());
    setState(value);
  };

  return [state, setStateHandler];
}

export default useLocalStorage;