개발/React

리액트 Custom Hook - 모든 페이지의 로컬 스토리지 변경 감지하기 (useLocalStorage)

피로물든딸기 2024. 4. 15. 22:10
반응형

리액트 전체 링크

 

참고

- 로컬 스토리지 사용 방법과 세션 스토리지 비교

- 게으른 초기화로 useState 초기화하기

 

다음과 같이 로컬 스토리지 변경을 감지하는 커스텀 훅을 만들어보자.

여기서는 모든 페이지에 대해 이벤트를 감지한다.

 

예시 코드는 다음과 같다.

로컬 스토리지가 변경되면 useEffect에서 storage 변경 이벤트 리스너를 등록하면 된다.

import React, { useState, useEffect } from "react";

const KEY0 = "MY_DATA_0";

const LocalStorageHook = () => {
  const [localStorageData, setLocalStorageData] = useState(
    localStorage.getItem(KEY0)
  );

  useEffect(() => {
    const handleStorageChange = () => {
      setLocalStorageData(localStorage.getItem(KEY0));
    };

    window.addEventListener("storage", handleStorageChange);

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

  const handleChange = (e) => {
    const newData = e.target.value;
    localStorage.setItem(KEY0, newData);
    setLocalStorageData(newData);
  };

  return (
    <div style={{margin : 5}}>
      <input type="text" value={localStorageData} onChange={handleChange} />
      <p>Local Storage Data: {localStorageData}</p>
    </div>
  );
};

export default LocalStorageHook;

useLocalStorage

 

위의 코드를 이용하여 useLocalStorage를 만들 수 있다.

key 값을 전달받아 내부에서 useEffect "storage" 이벤트 핸들러를 추가하고 선언한 useState를 반환한다.

useState 초기화는 게으른 초기화를 이용하였다.

const useLocalStorage = (key) => {
  const [data, setData] = useState(() => {
    let item = localStorage.getItem(key);
    return item === null ? "" : item;    
  });

  useEffect(() => {
    const handleStorageChange = () => {
      let item = localStorage.getItem(key);
      setData(item === null ? "" : item);
    };

    window.addEventListener("storage", handleStorageChange);

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

  return [data, setData];
};

 

이제 key 값에 대해 useLocalStoragehook을 가져와서 사용하면 된다.

const KEY0 = "MY_DATA_0";
...

const LocalStorageHook = () => {
  const [localStorageData0, setLocalStorageData0] = useLocalStorage(KEY0);
  ...
  
  const handleChange = (e, key, setState) => {
    const newData = e.target.value;
    localStorage.setItem(key, newData);
    setState(newData);
  };

  return (
    <div style={{ margin: 5 }}>
      <input
        type="text"
        value={localStorageData0}
        onChange={(e) => handleChange(e, KEY0, setLocalStorageData0)}
      />
      <p>Local Storage Data 0: {localStorageData0}</p>
      ...
    </div>
  );
};

export default LocalStorageHook;

 

전체 코드는 다음과 같다.

import React, { useState, useEffect } from "react";

const useLocalStorage = (key) => {
  const [data, setData] = useState(() => {
    let item = localStorage.getItem(key);
    return item === null ? "" : item;    
  });

  useEffect(() => {
    const handleStorageChange = () => {
      let item = localStorage.getItem(key);
      setData(item === null ? "" : item);
    };

    window.addEventListener("storage", handleStorageChange);

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

  return [data, setData];
};

const KEY0 = "MY_DATA_0";
const KEY1 = "MY_DATA_1";

const LocalStorageHook = () => {
  const [localStorageData0, setLocalStorageData0] = useLocalStorage(KEY0);
  const [localStorageData1, setLocalStorageData1] = useLocalStorage(KEY1);

  const handleChange = (e, key, setState) => {
    const newData = e.target.value;
    localStorage.setItem(key, newData);
    setState(newData);
  };

  return (
    <div style={{ margin: 5 }}>
      <input
        type="text"
        value={localStorageData0}
        onChange={(e) => handleChange(e, KEY0, setLocalStorageData0)}
      />
      <p>Local Storage Data 0: {localStorageData0}</p>
      <input
        type="text"
        value={localStorageData1}
        onChange={(e) => handleChange(e, KEY1, setLocalStorageData1)}
      />
      <p>Local Storage Data 1: {localStorageData1}</p>
    </div>
  );
};

export default LocalStorageHook;
반응형