코리아 IT아카데미/react.js

8일차 | API로 users 목록 불러오기, user 정보 나타내기

Sharon kim 2022. 3. 23. 12:02

 

yarn add axios
yarn add react-async

App.js

import React from 'react';
import Users from './components/users';
 //yarn add axios

 //https://jsonplaceholder.typicode.com/users
function App() {
  return (
      <Users/> 
    
  );
}

export default App;

 

useAsync.js

import {useReducer, useEffect} from "react";

function reducer(state, action) {
  switch (action.type) {
    case "LOADING":
      return {
        loading: true,
        data: null,
        error: null,
      };
    case "SUCCESS":
      return {
        loading: false,
        data: action.data,
        error: null,
      };
    case "ERROR":
      return {
        loading: false,
        data: null,
        error: action.error,
      };
    default:
      throw new Error("${action.type} 예외발생!");
  }
}

function useAsync(callback, deps = [], skip = false) {
  const [state, dispatch] = useReducer(reducer, {
    loading: false,
    data: null,
    error: null,
  });

  const fetchData = async () => {
    dispatch({type: "LOADING"});
    try {
      const data = await callback();
      dispatch({type: "SUCCESS", data});
    } catch (e) {
      dispatch({type: "ERROR", error: e});
    }
  };

  useEffect(() => {
    if (skip) return;
    fetchData();
  }, deps);
  return [state, fetchData];
}

export default useAsync;

 

user.jsx

import React from "react";
import axios from "axios";
import useAsync from "../useAsync";

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

function User({id}) {
  const [state] = useAsync(() => getUsers(id), [id]);
  const {loading, data: user, error} = state;

  if (loading) 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.jsx

import React, {useState} from "react";
import axios from "axios";
import useAsync from "../useAsync";
import User from "./user";

// useAsync에서는 Promise의 결과 바로 data에 담기 때문에, 요청을 한 이후 response에서 data 추출하여 반환하는 함수를 따로 만듬
async function getUsers() {
  const response = await axios.get(
    "https://jsonplaceholder.typicode.com/users"
  );
  return response.data;
}

function Users() {
  const [userId, setUserId] = useState(null);
  const [state, refetch] = useAsync(getUsers, [], true);

  const {loading, data: users, error} = state;

  if (loading) return <div>로딩중...</div>;
  if (error) return <div>에러가 발생!!!</div>;
  if (!users) return <button onClick={refetch}>불러오기</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={refetch}>다시 불러오기</button>
      {userId && <User id={userId} />}
    </>
  );
}

export default Users;

 

index.css

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}