REACT) localstorage가 바로 저장되지 않는다면?

김명성·2022년 5월 15일
3

REACT

목록 보기
32/32

localstorage에 setItem을 통해 값을 저장했을 때, 즉시 반영이 안되는 것처럼 보이는 경우가 있다.
원인은 localstorage.setItem() 메서드가 어떤 함수의 내부에 있어, setItem이 컴포넌트의 재실행에 의한 트리거가 되지 않는 경우인데,
해결하는 방법은 매우 간단하나, 왜 이러한 현상이 일어나는지 정확한 원인을 알고 싶었다.

혹시 비동기로 움직여서 storage에 저장하려는 값을 가져오기 전에 실행되서 그런건 아닐까 했지만, localstorage는 동기적으로 움직인다고 한다.

원인에 대한 해답은 다음과 같다.

The storage event of the Window interface fires when a storage area (localStorage) has been modified.The storage event is only triggered when a window other than itself makes the changes.

storage setItem 이벤트는 localstorage가 변경될 때마다 갱신되는게 아니라 window가 변경될 때만 트리거된다는 것이다.

컴포넌트가 재실행,재평가,랜더링 되면 위에서부터 아래로 코드를 읽고 React.DOM에게 알려, 실제 DOM과의 비교를 통해 Rendering된다.
그런데 클릭과 같은 이벤트에 의해 trigger가 되는 함수 내부에 setStorage가 있다면, Window는 변경사항을 알지 못하고 넘어가게 되는 것이다.

  const onSubmit = (e,func) => {
    const storedLocalProducts =
      JSON.parse(localStorage.getItem('product')) || [];
    e.preventDefault()
    setStoredProduct([productInformation, ...storedLocalProducts]);
    
    func()
    // setItem으로 localstorage가 변경되지만, window는 알지 못한다.
    localStorage.setItem('product', JSON.stringify(storedProduct));
  };

form을 제출할 때마다, onSubmit이 실행된다.
setItem을 실행하고 onSubmit은 실행 컨텍스트를 빠져나가는데,
setItem으로 localstorage의 변경은 일어나지만, window가 직접 변경되지 않기에(localstorage에 저장하는 행위는 Side Effectg이다.) 아무일도 일어나지 않은 것처럼 보인다. 하지만 localstorage에는 저장이 되어 있다.
페이지가 새로고침될 때 업데이트되지만 새 항목이 기존 항목을 추가하거나 업데이트할 때는 업데이트되지 않는 것이다.

해결 방법은 매우 간단하다

 useEffect(() => {
    if (storedProduct?.length === 0) {
      return;
    }
    localStorage.setItem('product', JSON.stringify(storedProduct));
  }, [storedProduct]);

컴포넌트가 재실행될때마다 DOM이 직접 알 수 있게 localstorage.setItem을 바깥으로 뺀다면, 이벤트에 의한 trigger가 아닌, 컴포넌트의 재실행에 의한 trigger가 되므로 항상 최신의 localstorage를 얻을 수 있다.

0개의 댓글