[RandomUserApplication NINJA] ExploreUsers 페이지 useSWR 지식 (5)

전역 옵션

  • SWRconfig 컴포넌트를 사용하여 적용한다.
import useSWR, { SWRConfig } from 'swr'

function Dashboard () {
  const { data: events } = useSWR('/api/events')
  const { data: projects } = useSWR('/api/projects')
  const { data: user } = useSWR('/api/user', { refreshInterval: 0 }) // override

  // ...
}

function App () {
  return (
    <SWRConfig 
      value={{
        refreshInterval: 3000,
        fetcher: (resource, init) => fetch(resource, init).then(res => res.json())
      }}
    >
      <Dashboard />
    </SWRConfig>
  )
}

하위 컴포넌트에 같은 옵션을 적용시켜 요청. 오버라이딩도 가능하다!

오류는 어떻게 처리해 ?

비동기 요청은 보통 오류를 try-catch문으로 제어한다. 그럼 fetcher를 구현해놓고 사용하는 useSWR의 경우는 어떻게 할까?
다음 코드를 보자.

const fetcher = async url => {
  const res = await fetch(url)

  // If the status code is not in the range 200-299,
  // we still try to parse and throw it.
  if (!res.ok) {
    const error = new Error('An error occurred while fetching the data.')
    // Attach extra info to the error object.
    error.info = await res.json()
    error.status = res.status
    throw error
  }

  return res.json()
}
  const res = await fetch(...args);

다음과 같이 async - await를 이용하여 응답을 받고 console에 찍어보면

같이 출력된다.
여기서 res.ok 변수를 이용하여 에러인지 아닌지를 판단하면된다.

export const fetcher = async (...args) => {
  // 인자들이 배열로 온다.
  const res = await fetch(...args);
  if (!res.ok) {
    const error = new Error("에러 발생 shitttt..");
    error.info = await res.json();
    error.status = res.status;
    throw error;
  }
  const data = await res.json();
  return data.results;

  //   return fetch(...args)
  //     .then((res) => res.json())
  //     .then((data) => data.results);
};

다음과 같이 수정해보았다. res.okfalse인 경우에는 error를 발생시킴.
응답에 성공하면 데이터를 받아 리턴한다.

오류 재시도


다음과 같이 오류 재시도도 가능하다.

자동 재검증

  • 브라우저를 두개에 우리 앱을 띄워놓는다고 가정

A 앱에서 로그인 하면 => B 앱에서도 로그인 되어있도록 자동재검증 가능



다음과 같이 계속해서 재검증( 재 요청)

키 값에 조건을 넣자

  • getKey라는 useSWRkey값을 가져오는 함수가 있다고 가정하자

만약 잘못된 키값을 반환한다면 ? 비동기 요청 수행하면 안된다 🥰

다음과 같이 조건부를 넣어 제대로 된 값인 경우에만 useSWR 수행하도록 한다.

// conditionally fetch
const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)

// ...or return a falsy value
const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)

// ...or throw an error when user.id is not defined
const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)

다음과 같이 다른 useSWR에 종속적인 데이터 요청도 수행가능하다

 const { data: user } = useSWR('/api/user')
  const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
  // When passing a function, SWR will use the return
  // value as `key`. If the function throws or returns
  // falsy, SWR will know that some dependencies are not
  // ready. In this case `user.id` throws when `user`
  // isn't loaded.

주석을 정리하자면, user에서 제대로된 값을 못받아오는 경우 비동기 요청 (swr) 수행 하지 않는다는 뜻.

다수 인자 전달

다음과 같은 경우는 문제 없는가 ?

useSWR('/api/user', url => fetchWithToken(url, token))

문제가 있다. 같은 키에 다른 token을 넣어서 요청한다 하더라도 결국 같은 키의 데이터이기 때문이다. 네트워크 요청이 각각 달라도 같은 키라니.. 좀 이상하다

이런 문제점을 고치려면 다음과 같은 방식을 사용하자

const { data: user } = useSWR(['/api/user', token], fetchWithToken)

토큰에 따라 키 값을 다르게 인지한다.

The function fetchWithToken still accepts the same 2 arguments, but the cache key will also be associated with token now.

키를 배열로 전달 ?

  • 다음과 같이 키 값을 배열로 전달한다면?
  const { data, error } = useSWR(["https://randomuser.me/api/?results=10", 10]);
  • ...args인 경우
export const fetcher = async (...args) => {
  console.log(args);
  // 인자들이 배열로 온다.
  //[1,2]로옴
  • args인 경우
export const fetcher = async (args) => {
  console.log(args);
  // 인자들을 배열로 넣었음에도 첫 번째 방만 온다. [1,2]에서 1만옴

아마 useSWR(첫번째인자,두번째인자)에서
첫번째 인자는 배열을 풀어서 두번째 인자 (fetcher)에 전달되는듯?
그래서 ...args 를 통해 배열로 만들어 준 다음 사용하는 듯

export const fetcher = async (...args) => {
  const [key, query] = args;
  console.log(key, query);

다음과 같이 사용하면 원하는 작업할 수 있게됨.

또는 다음과 같이

export const fetcher = async (args, query) => {
  console.log(args, query);

해서 사용해도됨

인자를 배열로 보내는 경우 정리

useSWR(첫 인자, 둘 인자)에서 첫 번째 인자가 배열이라면 useSWR 내부에서 이 배열을 ...args다음과 같이 풀어서 둘 인자인 fetcher로 전달해준다.

그렇기에

fetcher(arg1,arg2) 

처럼 사용하거나

fetcher(...args){
 const [arg1,arg2] = args 
}

처럼 사용해야함.

func(1,2,3)

	func(...args){
     console.log(args)
      // [1,2,3]임
    }

좋은 웹페이지 즐겨찾기