Frontend/swr

isLoding, isValidating 차이, 첫 로드, 업데이트 로드

개발하는루루 2024. 9. 8. 22:46

https://swr.vercel.app/ko/docs/getting-started

useSWR을 사용해서 데이터를 패칭하다보면 isLoading, isValidating이라는 걸 마주할 수 있다.

이를 활용하여 UI를 훨씬 더 센스있게 구현할 수 있다. (상황에 맞는 로딩 스켈레톤 적용할 수 있음)

이걸 이해하기 전에 SWR의 state machine 주기를 이해할 필요가 있다. 

 

SWR은 아래 상황에 따라 isLoading과 isValidating은 여러 의미를 가진다. 

 

1) 변하는 key가 없을 때

 

변하는 key가 없다면 isLoading은 첫 로드를 의미하며, isValidating은 mutate를 시킬 때만 true/false가 변환된다.

이를 UI로 활용해보면, 첫 로드는 isLoading으로 isValidating은 유저 액션에 따라 변경된 값을 보여줄 때의 loading으로 활용할 수 있다.

 

 

2) 변하는 key가 있을 때 

swr의 key에 변할 수 있는 변수를 담아줬을 때의 일이다. 

첫 로드는 1번과 비슷하게 일어나지만 key가 바뀔 때 isLoading도 같이 변한다.

 

그렇기 때문에 위와 같은 상황에서 첫 로드를 구현할 때 isLoading은 쓸 수 없다. 이유는 key가 바뀌면 또 로딩을 돌기 때문이다.

 

3) 아래와 같이 Previous Data를 true로 했을 때도 마찬가지 현상이 발생한다. 

previous data true option은 다음 mutate 혹은 리벨리데이트하기 전까지 계속 같은 참조값을 유지하여 재렌더링이 일어나지 않도록 한다. 

(만약 설정이 되어있지 않다면 데이터를 리벨리데이트하거나 mutate할 때 api 응답값이 undefined가 된다. => 재렌더 유발)

 

 

2번 & 3번과 같은 상황에 있어서 isValidating은 변수의 의미 그대로 동작하지만 isLoading은 "첫로드"를 기대한다면 그 동작과는 다르다는 것을 알 수 있다. 첫 로드를 구현하기 위해 나는 아래와 같이 설계했다. 

 

  const { data: openAt, error } = useSWR(
    isFocused ? ["palm-staking-open", chainID] : null,
    async ([, _chainID]) => {
      if (!_chainID) return undefined;
      return PalmStakingController.getRewardStart();
    },
    {
      keepPreviousData: true,
    }
  );
  
  const isInitialLoad = !(openAt || error)

 

즉, 데이터를 성공적으로 fetch하면 undefined가 아닐 것이고, 실패하면 error가 생길 것이다. 

그 점을 활용하여 이용할 수 있다. 

 

혹은 keepPreviousData가 true면 SWR의 onError를 활용할 수 있다. 

 

  const { data: openAt } = useSWR(
    isFocused ? ["palm-staking-open", chainID] : null,
    async ([, _chainID]) => {
      if (!_chainID) return undefined;
      return PalmStakingController.getRewardStart();
    },
    {
      keepPreviousData: true,
      onError: () => return undefined;
    }
  );
  
  const isInitialLoad = !(openAt)

왜냐하면, keepPreviousData가 true이니 첫 데이터가 로드되면 이후엔 undefined가 되지 않는다.

그리고 error일 때 data를 undefined로 확실하게 처리하면, data의 유무로만 판단해도 된다. 

 

 

 

 

참고: https://swr.vercel.app/docs/advanced/understanding