[React/리액트] react-async 로 요청상태 관리하기
react-async
는 useAync
와 비슷한 함수가 들어있는 라이브러리이다.
이 라이브러리 안에 들어있는 함수 이름도 useAsync
인데, 사용법이 조금 다르다.
만약 매번 프로젝트를 만들때마다 직접 요청 상태 관리를 위한 커스텀 Hook을 만들기 귀찮다면 이 라이브러리를 사용하면 된다.
기존에 만들었던 커스텀 Hook은 결과물을 배열로 반환했다면, 이 Hook은 객체 형태로 반환한다.
설치
$ yarn add react-async
사용법
react-async 의 useAsync
를 사용할 때 파라미터로 넣는 옵션 객체에는 호출 할 함수 promiseFn
을 넣고, 파라미터 필드 이름과 함께 (customerId
) 넣어주어야 한다.
예시)
import { useAsync } from "react-async"
const loadCustomer = async ({ customerId }, { signal }) => {
const res = await fetch(`/api/customers/${customerId}`, { signal })
if (!res.ok) throw new Error(res)
return res.json()
}
const MyComponent = () => {
const { data, error, isLoading } = useAsync({ promiseFn: loadCustomer, customerId: 1 })
if (isLoading) return "Loading..."
if (error) return `Something went wrong: ${error.message}`
if (data)
return (
<div>
<strong>Loaded some data:</strong>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
return null
}
User/Users.js 컴포넌트 전환
위 컴포넌트들을 react-aync 의 useAsync
로 전환해보자!
* useAsync
사용 시 프로미스를 반환하는 함수의 파라미터를 객체 형태로 해주어야 한다.
async function getUser({ id }) {}
👉 그래야 id
값을 따로 받아와서 사용할 수 있게 된다.
* watch
값에 특정 값을 넣어주면 이 값이 바뀔 때마다 promiseFn
에 넣은 함수를 다시 호출해준다.
User.js
import React from "react";
import axios from "axios";
import { useAsync } from "react-async";
async function getUser({ id }) {
const response = await axios.get(
`http://jsonplaceholder.typicode.com/users/${id}`
);
return response.data;
}
/* useAsync 사용 시 프로미스를 반환하는 함수의 파라미터를 객체 형태로 해주어야 한다. */
function User({ id }) {
// id 값이 바뀔 때 마다 함수를 호출
const {
data: user,
error,
isLoading,
} = useAsync({
promiseFn:
getUser /* 컴포넌트가 처음 렌더링 될 때 getUser의 파라미터로 id를 넣고 호출 */,
id,
watch: id /* id 값이 변경되면 useAync 다시 호출 (=deps와 비슷) */,
});
if (isLoading) return <div>로딩중..</div>;
if (error) return <div>에러가 발생했습니다.</div>;
if (!user) return null;
return (
<div>
<h2>{user.username}</h2>
<p>
<b>Email: </b> {user.email}
</p>
</div>
);
}
export default User;
Users.js
import React, { useState } from "react";
import axios from "axios";
import { useAsync } from "react-async";
import User from "./User";
// useAsync.js Hook 함수로 넘겨주는 callback 함수
async function getUsers() {
const response = await axios.get(
"http://jsonplaceholder.typicode.com/users/"
);
return response.data;
}
function Users() {
const [userId, setUserId] = useState(null);
/* 여기서 reload는 이전에 구현한 refetch와 동일 */
const {
data: users,
error,
isLoading,
reload,
} = useAsync({
promiseFn: getUsers,
});
// users, loading, error 3가지 상태에 따라 다른 결과물을 반환하도록 설정
if (isLoading) return <div>로딩중..</div>;
if (error) return <div>에러가 발생했습니다</div>;
if (!users) return <button onClick={reload}>불러오기</button>;
return (
<>
<ul>
{users.map((user) => (
<li key={user.id} onClick={() => setUserId(user.id)}>
{user.username} ({user.name})
</li>
))}
</ul>
<button onClick={reload}>다시 불러오기</button>
{userId && <User id={userId} />}
</>
);
}
export default Users;
장/단점
장점
- 옵션이 다양하다 (promiseFn, deferFn, watch 등)
- 다양한 기능 (요청 취소)
- Hook을 만들 필요 없이 바로 불러와서 사용할 수 있다
단점
- 객체 안에 다양한 값이 들어있어서 헷갈릴 수 있다 (run, reload 등)