- Promise란 비동기 처리에서 사용되는 객체로, promise가 상태를 관리하여 다른 코드가 비동기적으로 실행될 수 있도록 만드는 객체이다.
👉 axios 또한 promise를 기반으로 만들어짐
- '.then' 문법에 의해 생기는 '콜백지옥'을 극복하기 위해 만들어진 문법으로, async는 함수 이름의 제일 앞에, await는 결과를 기다릴 함수 앞에 작성한다.
👉 async는 함수에서 비동기 처리를 위한 promise 동작을 한다는 것을 명시한다.
👉 await은 호출되는 함수가 적절한 결과를 반환할 때까지 기다리도록 동작한다.
function resolveAfter2Seconds() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("resolved");
}, 2000);
});
}
async function asyncCall() {
console.log("calling");
const result = await resolveAfter2Seconds();
console.log(result);
}
🔥 호출 과정
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function Users() {
// state인 users를 useState()로 선언하기
const [users, setUsers] = useState([]);
// async와 await를 이용한 useEffect()를 선언하기
useEffect(()=>{
async function fetch() {
const response = await axios.get('<URL>');
// 일단 response의 형태를 확인하고
console.log(response.data);
// fetch 함수 아래에 setUsers를 해주어야 한다.
setUsers(response.data);
};
fetch();
}, [])
// users 출력
const userName = users.map(
(user) => (<li key={user.id}> {user.name} </li>)
);
return (
<>
<h4>사용자 리스트</h4>
<div> {userName} </div>
</>
);
}
export default Users;
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function Users() {
const [users, setUsers] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchUser() {
// try ~ catch를 이용해 예외 처리를 하세요.
try {
const response = await axios.get(
'https://jsonplaceholder.typicode.com/error'
);
setUsers(response.data);
} catch(e) {
setError(e);
}
};
fetchUser();
}, []);
if (error) return <h4>에러 발생!</h4>;
...
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function Users() {
const [users, setUsers] = useState([]);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
async function fetchUser() {
// 함수가 처음 시작할 때 loading state를 true, 끝날 때 false로 설정
setLoading(true);
try {
const response = await axios.get(
'<URL>'
);
setUsers(response.data);
} catch (e) {
setError(e);
}
setLoading(false);
};
useEffect(() => {
fetchUser();
}, []);
const handleButtonClick = () => {
fetchUser();
}
const userName = users.map(
(user) => (<li key={user.id}> {user.name} </li>)
);
if(loading)
return <h4>로딩중...</h4>;
return (
<>
<h4>사용자 리스트</h4>
<div> {userName} </div>
{/* 버튼 클릭 시 fetchUser() 함수를 불러오는 이벤트를 등록 */}
<button onClick={handleButtonClick}>다시 불러오기</button>
</>
);
}
function reducer(state, action) {
switch (action.type) {
case 'LOADING':
return {
loading: true,
data: [],
error: null
};
case 'SUCCESS':
return {
loading: false,
data: action.data,
error: null
};
case 'FAIL':
return {
loading: false,
data: [],
error: action.error
};
default:
throw new Error();
}
}
const initState = { loading: false, data: [], error: null }
const [state, dispatch] = useReducer(
reducer,
initState,
);
async function fetchUser() {
try {
// dispatch를 이용해 state를 설정하는 코드입니다.
dispatch({ type: 'LOADING' });
const response = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
dispatch({ type: 'SUCCESS', data: response.data });
} catch (e) {
dispatch({ type: 'FAIL', error: e });
}
};
useEffect(() => {
fetchUser();
}, []);
// useReducer의 state를 불러오는 코드
const { loading, data, error } = state;
여기를 참고해서 만들었다. 아래 주소에는 html을 이용해 만드는 방법이 소개되어 있다.
👉 Using Axios to Pull Data from a REST API
React를 이용해 Pokemon API를 호출해서 포켓몬 리스트를 출력해 본다.
<App.js>
import React, { useState, useEffect } from 'react';
import axios from 'axios'
import PokemonList from './PokemonList'
import Pagination from './Pagination';
function App() {
const [pokemon, setPokemon] = useState([])
const [currentPageUrl, setCurrentPageUrl] = useState("https://pokeapi.co/api/v2/pokemon")
const [nextPageUrl, setNextPageUrl] = useState()
const [prevPageUrl, setPrevPageUrl] = useState()
const [loading, setLoading] = useState(true)
const [] = useState()
useEffect(() => {
setLoading(true)
let cancel
// 포켓몬 데이터를 불러오고 cancelToken을 함께 넘겨준다. 그리고 state를 설정한다.
async function fetch() {
const response = await axios.get(currentPageUrl, { cancelToken: new axios.CancelToken(c => cancel = c) })
console.log(response.data);
setLoading(false);
setNextPageUrl(response.data.next);
setPrevPageUrl(response.data.previous);
setPokemon(response.data.results.map(p=> p.name))
}
fetch();
// 페이지 이동이 취소되는 경우 현재 페이지를 유지
return () => cancel()
}, [currentPageUrl])
// 다음 페이지로 이동
function gotoNextPage() {
setCurrentPageUrl(nextPageUrl)
}
// 이전 페이지로 이동
function gotoPrevPage() {
setCurrentPageUrl(prevPageUrl)
}
// 로딩 상태인 경우 로딩중을 출력
if (loading) return "로딩중..."
return (
<>
<PokemonList pokemon={pokemon} />
<Pagination
gotoNextPage={nextPageUrl ? gotoNextPage : null}
gotoPrevPage={prevPageUrl ? gotoPrevPage : null}
/>
</>
);
}
export default App;
<PokemonList.js>
import React from 'react'
export default function PokemonList({ pokemon }) {
return (
<div>
{pokemon.map(p => (
<div key={p}>{p}</div>
))}
</div>
)
}
<Pagination.js>
import React from 'react'
export default function Pagination({ gotoNextPage, gotoPrevPage }) {
return (
<div>
{gotoPrevPage && <button onClick={gotoPrevPage}>Previous</button>}
{gotoNextPage && <button onClick={gotoNextPage}>Next</button>}
</div>
)
}
🐧 이 글은 엘리스 AI 트랙 2기 react 강의 내용을 바탕으로 작성되었습니다.