Front-End/React.js

React.js | API 연동 | react-async로 요청 상태 관리하기

개발자티포 2021. 10. 7. 17:48
728x90
반응형

react-async는 우리가 지난 섹션에서 만들었던 useAsync와 비슷한 함수가 들어있는 라이브러리다.

이름은 똑같으나 사용법이 조금 다르다.

 

만약 매번 프로젝트를 만들 때 마다 직접 요청 상태 관리를 위한 커스텀 Hook을 만들기 귀찮으면

이 라이브러리를 사용하면 유용할 것이다.

 

먼저 react-async를 설치한다.

$ npm i react-async

 

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
}

react-async의 useAsync 를 사용 할 때 파라미터로 넣는 옵션 객체에는 호출 할 함수 promiseFn 을 넣고, 파라미터도 필드 이름과 함께 costomerId를 넣어주어야 한다.

 

User 컴포넌트 전환

User 컴포넌트를 react-async의 useAsync 로 전환하자

import React from 'react';
import axios from 'axios';
import { useAsync } from 'react-async';

async function getUser({ id }) {
  const response = await axios.get(
    `https://jsonplaceholder.typicode.com/users/${id}`
  );
  return response.data;
}

function User({ id }) {
  const { data: user, error, isLoading } = useAsync({
    promiseFn: getUser,
    id,
    watch: id
  });

  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;

 

react-async를 사용할 때에는 프로미스를 반환하는 함수의 파라미터를 객체형태로 해주어야 한다.

async function getUser({ id }) {}

 

그리고 watch 값에 특정 값을 넣어주면 이 값이 바뀔 때마다 promiseFn에 넣은 함수를 다시 호출한다.

 

 

Users 컴포넌트 전환

Users.js

import React, { useState } from 'react';
import axios from 'axios';
import { useAsync } from 'react-async';
import User from './User';

async function getUsers() {
  const response = await axios.get(
    'https://jsonplaceholder.typicode.com/users'
  );
  return response.data;
}

function Users() {
  const [userId, setUserId] = useState(null);
  const { data: users, error, isLoading, reload } = useAsync({
    promiseFn: getUsers
  });

  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)}
            style={{ cursor: 'pointer' }}
          >
            {user.username} ({user.name})
          </li>
        ))}
      </ul>
      <button onClick={reload}>다시 불러오기</button>
      {userId && <User id={userId} />}
    </>
  );
}

export default Users;

 

 

이전에 사용했던 skip처럼 나중에 데이터를 불러오려면 promiseFn 대신 deferFn, reload 대신 run 함수를 사용한다.

 

Users.js

import React, { useState } from 'react';
import axios from 'axios';
import { useAsync } from 'react-async';
import User from './User';

async function getUsers() {
  const response = await axios.get(
    'https://jsonplaceholder.typicode.com/users'
  );
  return response.data;
}

function Users() {
  const [userId, setUserId] = useState(null);
  const { data: users, error, isLoading, run } = useAsync({
    deferFn: getUsers
  });

  if (isLoading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!users) return <button onClick={run}>불러오기</button>;

  return (
    <>
      <ul>
        {users.map(user => (
          <li
            key={user.id}
            onClick={() => setUserId(user.id)}
            style={{ cursor: 'pointer' }}
          >
            {user.username} ({user.name})
          </li>
        ))}
      </ul>
      <button onClick={run}>다시 불러오기</button>
      {userId && <User id={userId} />}
    </>
  );
}

export default Users;

 

 

정리 

  • 로그인 할 때는 최상위 컴포넌트에 쿠키를 state에 담고 상태를 관리해준다.(로그아웃, 프로필 수정)
  • 로그아웃 했을 경우(state가 null값이 될 때) 최상위에서 첫 화면 컴포넌트를 return 한다.
  • API가 필요한 경우 처음 페이지가 렌더링 될 때 useAsync로 state(리스트, 사진 등)를 만들어준다.
  • API 필요 없을 경우 처음 페이지 렌더링 될 때 useEffect를 사용해준다.
  • 추가, 수정, 삭제가 필요한 데이터의 경우 reducer를 만들어서 관리한다.(action으로 실행)
728x90
반응형