Stack/React

[React] API 연동하기 2

7ingout 2022. 6. 29. 12:09

App.js

import './App.css';
import UserCustomHook from './components/UsersCustomHook';
// import Posts from './components/Posts';
// import PostsReducer from './components/PostsReducer';
// import Users from './components/Users';
// import UsersReducer from './components/UsersReducer';

function App() {
  return (
    <div className="App">
      {/* <Users/>
      <UsersReducer/>
      <Posts/>
      <PostsReducer/> */}
      <UserCustomHook/>
    </div>
  );
}

export default App;

 

components/UsersCustomHook.js

// useAsync를 사용해서 비동기 전송을 받아와 사용
import React, { useState } from 'react';
import axios from 'axios';
import useAsync from './useAsync';
import User from './User';

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

const UserCustomHook = () => {
    const [userId, setUserId] = useState(null);
    const [state, refetch] = useAsync(getUsers, [], true);
    const { loading, data, error } = state;
    if(loading) return <div>로딩중...</div>
    if(error) return <div>에러가 발생했습니다.</div>
    if(!data) return <button onClick={refetch}>불러오기</button>
    return (
        <div>
             <ul>
                {data.map(user => (
                        <li key={user.id} onClick={()=>{
                            setUserId(user.id)
                        }}>
                            {user.username} ({user.name})
                        </li>
                    )    
                )}
            </ul>
            <button onClick={refetch}>다시 불러오기</button>
            {userId && <User id = {userId}/>}
        </div>
    );
};

export default UserCustomHook;

 

components/useAsync.js

import { useReducer, useEffect } from 'react';
const initialState = {
    loading: false,
    data: null,
    error: null
}
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: 
        return state;
}
}
function useAsync(callback, deps = [], skip = false) {
    const [ state, dispatch ] = useReducer(reducer, initialState);
    const fetchDate = async () => {
        dispatch({ type: "LOADING" });
        try{
            const data = await callback();
            dispatch({
                type: "SUCCESS",
                data: data
            })
        }
        catch(e) {
            dispatch({
                type: "ERROR",
                error: e
            })
        }
    }
    useEffect(()=>{
        // skip이 true면 리턴 fetchDate() 실행안됨
        if(skip) return;
        fetchDate();
        // ↓ eslint 설정을 다음 줄에서만 비활성화
        // eslint-disable-next-line
    }, deps)
    return [state, fetchDate];
}
export default useAsync;

 

Components/User.js

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

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

const User = ({id}) => {
    const [ state ] = useAsync(()=> getUser(id), [id]);
    const { loading, data, error } = state;
    if(loading) return <div>로딩중...</div>
    if(error) return <div>에러가 발생했습니다.</div>
    if(!data) return null
    return (
        <div>
            <h2>{data.username}</h2>
            <p>
                Email: {data.email}
            </p>
        </div>
    );
};

export default User;

.

.

.

2022.06.28 - [Coding/React] - [React] API 연동하기