useHistoryState, 뒤로가기/새로고침 페이지 상태 유지

웹브라우저의 기본 경험을 React SPA에서 구현할 때 사용하는 간단한 훅입니다.

import { useState, useCallback } from 'react';
import { useHistory } from 'react-router-dom';

const useHistoryState = (initialState, key) => {
  const history = useHistory();
  const stateValue = history.location.state?.[key];

  const [historyState, setHistoryState] = useState(
    stateValue === undefined ? initialState : stateValue,
  );

  const setState = useCallback(
    (state, replace = false) => {
      const value = state instanceof Function ? state(historyState) : state;

      setHistoryState(() => value);
      history.replace({
        state: replace ? value : { ...history.location.state, [key]: value },
      });
    },
    [history, historyState, key],
  );

  return [historyState, setState];
};

export default useHistoryState;

아래처럼 setState와 유사하게 사용합니다.

// useHistoryState(기본값, 키이름)
const [sort, setSort] = useHistoryState('desc', 'sort');
const [showPanel, setShowPanel] = useHistoryState(false, 'showPanel');

// or
const [pageForm, setPageForm] = useHistoryState({
  title: '',
  content: '',
  tags: [],
}, 'pageForm');


return (
  <>
    <select value={sort} onChange={({ target }) => setSort(() => target.value)}>
      <option value="desc">내림차순</option>
      <option value="acs">오름차순</option>
    </select>
    
    <label>
      <input
        type="checkbox"
        checked={showPanel}
        onChange={({ target }) => setShowPanel(() => target.checked)}
      />
      패널 표시
    </label>
  </>
);

이렇게 뒤로가기/앞으로가기, 새로고침 시 input에 입력한 값을 유지시켜서 브라우저 기본 동작처럼 자연스럽게 동작하도록 구현할 때 사용합니다. 그리고 SWR과 조합하여 뒤로가기 시 캐시를 활용하고 API 요청을 하지 않도록 처리합니다.