SWR 간단한 사용방법

최준호·2024년 3월 19일
0

FingooProject

목록 보기
1/3
post-thumbnail
  • 이번 프로젝트 온보딩 과정에서 SWR라이브러리를 몰라서 코드 읽기가 힘들어서 공부 시작했음
    화이팅화이팅!!

SWR

  • 캐시(stale)로부터 데이터를 반환한 후, fetch 요청(revalidate)하고, 최신화된 데이터를 가져옴

⇒ 컴포넌트가 지속적이고, 자동으로 데이터 업데이트 스트림을 받음, 빠르고 반응적인 UI


사용방법

설치

//npm
npm i swr
//yarn
yarn add swr

기본적인 사용방법

const fetcher = (...args) => fetch(...args).then(res => res.json())
// 함수 컴포넌트
import useSWR from 'swr'
function Profile() {
	const {data, error, isLoading} = useSWR('/api/user/123', fetcher)
	if (error) return <div>fail to load</div>
	if (isLoading) return <div>Loading...</div>
	
	//data rendering
	return <div>hello{data.name}</div>
}
  • JSON 데이터를 사용하는 RESTful API일 때 이를 호출하는 fetcher함수 생성
  • useSWR 훅을 사용해 데이터를 관리
    • useSWR(1st Argument: key, 2nd Argument: fetcher함수, 3rd Argument: options)
      • fetcher함수에 첫 번째 인자를 파라미터로 전달
      • fetcher함수는 promise 리턴하는 함수가 올 수 있어 axios와 같은 별도 라이브러리 사용가능
    • isLoading, data, error 세 가지의 상태를 통해 요청의 상태 확인, 해당 UI반환
      • data : fetcher가 이행한 키에 대한 데이터. 로드되지 않으면 undefined
      • error : fetcher가 던진 error. 로드되지 않으면 undefined
      • isLoading : 진행중인 요청 있고, 로드된 데이터가 없는 경우

Axios 활용해 useSWR활용

import axios from 'axios'

const fetcher = url => axios.get(url).then(res => res.data)

function App() {
	const {data, error} = useSWR('/api/data', fetcher)
	...
}

조건부로 가져오기

const {data} = useSWR(shouldFetch ? '/api/data' : null, fetcher)
const {data} = useSWR(() => shouldFetch ? '/api/data' :null, fetcher)
const {data} = useSWR(() => '/api/data?uid=' + userid, fetcher)
  1. 조건부로 가져오기
  2. 조건부로 가져오거나 falsy 값 반환
  3. 조건부로 가져오거나 user.id가 정의되지 않았을 때 error
function MyProjects() {
	const {data:user} = useSWR('/api/user')
	const {data: projects} = useSWR(() => '/api/projects?uid=' + user.id)
	if(!projects) return 'loading'
	return projects.length
  • 함수 전달시에 SWR은 반환 값을 ‘key’로 사용
  • 함수가 falsy를 던지거나 로드되지 않으면 에러발생시킴

인자

//세 가지 표현식은 모두 동일
useSWR('/api/user', () => fetcher('/api/user')
useSWR('/api/user', url => fetcher(url))
useSWR('/api/user', fetcher)
  • fetcher 함수에 여러 인자를 전달할 때 → 다중 인자를 포함하는 배열을 key 파라미터 사용가능
const {data:user} = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url,token))
  • fetchWithUser(api,user) 함수가 있을 때 객체를 키로 바로 전달할 수 있고, fetcher가 그 객체를 받는다.
//객체를 받고 또다른 인자로 전달하는 경우
const {data: user} = useSWR(['api/user',token], fetchWithToken)
const {data: orders} = useSWR(user ? ['/api/orders',user] : null, fetchWithUser)

//객체를 키로 바로 전달하고 fetcher가 그 객체를 받는 경우
const {data:orders} = useSWR({url:'/api/orders', args: user}, fetcher)

Mutation & Revalidation

  • mutate ⇒ 데이터를 변경하거나 업데이트를 하는 동작을 수행하는 메서드
  • Global Mutate → 모든 키를 변경
//useSWRConfig Hook 사용하기(권장)
import {useSWRConfig} from "swr"
function App() {
	const {mutate} = useSWRConfig()
	mutate(key, data, options)
}

//전역으로 가져오기
import {mutate} from "swr"
function App() {
	mutate(key, data, options)
}

Bound Mutate → 현재 키를 기반으로 데이트 변경, key 매개변수가 필요 없음

  • requstUpdateUsername(newName)에서 데이터를 업데이트
  • 로컬 데이터를 업데이트하고 다시 유효성검사(refetch)
import useSWR from "swr"

function Profile() {
	const {data, mutate} = useSWR('/api/user', fetcher)
	
	return (
		<div>
			<h1>My name is {data.name}.</h1>
      <button onClick={async () => {
				const newName = data.name.toUpperCase()
        await requestUpdateUsername(newName)
        mutate({...data, name: newName})
			}}>Upeercase name</button>
		</div>
	}
}
  • Revalidation → 데이터 없이 mutate(key) 호출시 리소스에 대한 재검증 실시
    • 재검증 : SWR에서 데이터가 만료된 것을 감지, 서버로부터 데이터를 재검색하는 과정을 의미
  • 아래 코드 : Logout 버튼 클릭시 해당 키에 대한 재검증 실시
import useSWR, { useSWRConfig } from 'swr'
 
function App () {
  const { mutate } = useSWRConfig()
 
  return (
    <div>
      <Profile />
      <button onClick={() => {
        document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'
         // `/api/user` 라는 키를 가진 모든 SWR에게 재검증을 지시합니다.
        mutate('/api/user')
      }}>
        Logout
      </button>
    </div>
  )
}
  • useSWRMutation : 데이터 변경 작업을 비동기적으로 트리거하고, 결과를 처리
    • remote mutation ⇒ 자동으로 트리거 되는 것이 아닌 수동으로 트리거된다.
    • 다른 useSWRMutation hook과 상태를 공유하지 않는다. ⇒ 별도로 사용
  • useSWRMutation(key, fetcher(key, {arg}) → remote mutation을 위한 비동기함수, optional객체
  • 반환값 : data, error, trigger(arg, options)→ remote mutation을 트리거하는 함수 …
import useSWRMutation from 'swr/mutation'

async function updateUser(url, {arg}: {arg: string}) {
	await fetch(url, {
		method: 'POST',
		headers: {
			Authorization: `Bearer ${args}`
		}
	})
}

function Profile() {
	const {trigger} = useSWRMutation('/api/user', updateUser, options)
	
	return <button onClick={() => {
		trigger('my_token')
	})>UpdateUser</button>
}

TypeScript

  • SWR은 key로부터 fetcher의 인자타입 추론해 자동으로 사용 가능
useSWR('api/user', key=>{}) //key가 string으로 추론된다.

useSWR({a:'1', b:{c:'3',d:2}}, key=>{}) //key가 {a:string,b:{c:string,d: number}}

useSWR(['user',8], ([arg0, arg1]) => {}) //arg0: string, arg1: number로 추론
  • Key와 Fetcher 인자 타입 명시적으로 지정 가능
import useSWR, {Fetcher} from 'swr'

const uid='<user_id>'
const fetcher: Fetcher<User, string>= (id) => getUserById(id) //첫번째 매개변수 string, 반환타입 : user
const {data} : {data: User | undefined} = useSWR(uid, fetcher)
  • data → fetcher의 반환 타입을 사용하는데 파라미터로 전달할 수 있음
//타입 지정된 fetcher 사용
// getUser : (endpoint: string) => User
const {data} = useSWR('/api/user', getUser)

//데이터 타입 지정
const {data} = useSWR<User>('/api/user', fetcher)
  • SWR 옵션에 타입 추가
profile
FE Developer(진)

0개의 댓글