TIL

React

배포 전 테스트 2

React-Query와 useState() 그 사이..

아이템 리스트 페이지에서 아이템 A에 대한 쿼리 데이터를 받아온 뒤
-> 아이템 A에 대한 수정 페이지로 이동

수정 페이지에서는 이미 해당 아이템에 대한 데이터가 캐싱되어 있어서 처음에는 데이터 접근이 수월한 것처럼 보인다.
하지만 이후 수정 페이지에서 새로고침을 하게되는 경우 캐싱된 데이터가 사라져 수정 페이지에서 데이터 페칭을 시도한다.
지금까지의 로직에서, 수정 페이지에서는 데이터가 있다고 생각하고 당당하게 접근해왔고, undefined 에러에 휩싸였다.

고민해본 개선방법

  1. 어플리케이션 로직에서 데이터 페칭을 기다렸다가 UI 컴포넌트에 데이터를 보내주기
    • 장점: 여전히 당당하게 UI 컴포넌트에서 데이터에 접근할 수 있다.
    • 단점: 느린 네트워크 환경에서 데이터 페칭이 완료될 때까지 빈 페이지를 봐야함
  2. 어플리케이션 로직에서 데이터 페칭중 / 완료를 나눠서 UI 그리기
    • 장점: 스켈레톤 뷰가 있는 경우 적합
    • 단점: 두 가지의 UI 뷰를 고려해야 함
    • 문제상황 발생
      스켈레톤 뷰가 없는 우리는 페칭중/완료 모두 같은 UI뷰를 사용하고 itemData만 다르게 넣어준다.
      이때 편집 컴포넌트에서 정보 수정을 위한 여러 input 태그를 사용하고 있다.
      input 핸들링을 위해 useState()를 이용하고 있고, 초깃값은 서버 데이터를 이용한다.
      그리고 이벤트가 발생되지 않는 input의 placeholder 속성은 서버 데이터를 바로 연결한 상태.
function ItemEdit({ itemData }) {
  const [nickname, setNickname] = useState(itemData.nickname);
  const [price, setPrice] = useState(itemData.price);

  return (
    <form>
      <input type="text" value={nickname} placeholder={itemData.nickname} />
      <input type="number" value={price} placeholder={itemData.price} />
    </form>
  )
}

이 경우 뷰에서는 value 없이 placeholder만 나온 상태이다.
여기서 문제는 itemData가 undefined일 때 (데이터 페칭중) 처음 마운트되어, 이미 useState의 초깃값으로 설정이 되었고, 이후 itemData가 페칭 완료되어 리렌더링이 발생되면 state는 유지되고, placeholder에서만 접근 가능한 상태가 된다는 것이다.

function ItemEdit({ itemData }) {
  const [nickname, setNickname] = useState(itemData.nickname);
  const [price, setPrice] = useState(itemData.price);

  useEffect(() => {
    setNickname(itemData.nickname);
    setPrice(itemData.price);
  }, [itemData]);

  return (
    <form>
      <input type="text" value={nickname} placeholder={itemData.nickname} />
      <input type="number" value={price} placeholder={itemData.price} />
    </form>
  )
}

useEffect()를 이용하여 리렌더링 시에 다시 서버 데이터를 넣어준다면?
원하는 뷰를 얻을 수 있지만, 느린 네트워크 환경에서 수정 후 mutate를 하는 경우 다시 리렌더링이 발생하며
itemData가 다시 초기값으로 세팅되어 순간적으로 수정 이전의 데이터가 form에 보인다.

종속성을 수정하는 방식을 시도해보다가,
결국 밖에서 데이터 페칭 조건 전후 ItemEdit 컴포넌트에 key를 다르게 부여하여 새로 마운팅되도록 하여, 서버 데이터를 useState()의 초기값으로 세팅할 수 있도록 했다.

하지만 결론적으로 빠른 네트워크에서는 빈 폼과 데이터가 있는 폼이 깜박이는 것처럼 보이고,
느린 네트워크에서도 빈 폼인 동안 사용자의 입력을 잘못 유도하는 것 같아
기존의 수정 로직을 모두 삭제하고, 데이터 페칭중에는 스피너를 렌더링하는 방식으로 수정했다 :)

React-Query에 대해서 제법 다양한 케이스를 다뤄보며, 안전하게 서버 데이터에 접근할 수 있다고 생각했는데
역시 처음 써봤던 시기의 코드에는 구멍들이 숭숭 보이고, 아직도 고민이 되는 케이스들이 있는 것 같다!
그래도 덕분에 리렌더링과 리액트 훅 동작방식에 대해서 또 한번 복습해볼 수 있었다.