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;
import React, { useState } from "react";
import axios from 'axios';
import useAsync from '../useAsync';
import User from './user';
//api연결하는 함수
async function getUsers() {
const respones = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
return respones.data;
}
function Users() {
//상태관리
const [userId, setUserId] = useState(null);
const [state, refetch] = useAsync(getUsers, [], true);
//useAsync는 데이터를 요청할때마다 리덕스를 작성하는 것이 번거로운일이다
//매번 반복되는 코드를 작성하는 대신에 커스터hook을 만들어 요청상태 관리
//로직을 쉽게 재사용하는 함수
//상태에 대한 예외처리
const { loading, data: users, error } = state;
if (loading) return <div>로딩중...</div>
if (error) return <div>에러가 발생!!!</div>
if (!users) return <button xxxxonClick={refetch}>불러오기</button>;
return (
<div>
<ul>
{users.map(user => (
< li key={user.id} xxxxonClick={() => setUserId(user.id)} style={{ cursor: 'pointer' }} >
{user.username}({user.name})
</li>
))}
</ul>
<button xxxxonClick={refetch}>다시 불러오기</button>
{userId && <User id={userId} />}
</div >
)
}
export default Users;