지난 번 스탠다드 반에서 배운 axios, fetch를 통한 비동기 통신 내용은 아래 글을 확인하면 된다.
비동기 통신 - axios
axios란
axios 는 node.js와 웹 브라우저 모두를 위한 Promise 기반 http 클라이언트이다. http를 이용하여 서버와 통신을 하기 위해 만들어진 패키지이다.
axios (get) 하기
1. axios 패키지 설치
yarn add axios
2. json-server 설정하기
2-1. json-server 설치하기
yarn add json-server
2-2. test용 json-server 만들기 (json-server API 명세서)
root scope에 db.json 파일 추가하기
db.json 파일 안에 가상 데이터 추가하기
{
"todos": [
{
"id": "1",
"title": "react"
},
{
"id": "2",
"title": "node"
},
{
"id": "3",
"title": "next"
}
]
}
2-3 db.json 구동시키기(포트를 통해 브라우저에 띄우기)
yarn json-server --watch db.json --port 3001
** 왜 port가 다른가?
현재 client side인 localhost:3000은 리액트 어플리케이션이고, server side인 localhost:3001/todos는 서버이기 때문에 서로 물리적으로 다른 곳에 있는 컴퓨터이기 때문이다. 본래 클라리언트와 서버는 다른 컴퓨터에서 작동한다.
2-4 db.json 브라우저에서 확인하기
주소창
http://localhost:3001/todos
3. 데이터 요청 request 하기
3-1. mount가 될때 데이터를 요청해야 한다. 따라서 useEffect를 사용해야 한다.
useEffect (() => {
}, [])
3-2 데이터를 비동기적으로 가져오기
axios에서 request method는 'get'을 사용한다.
그리고 그것을 비동기적으로 처리하기 위해 async/await을 사용한다.
만약에 await이 없다면 아래와 같이 console.log 에 찍히는 값은 pending으로 개발자 도구에서 나온다.
WHY? axios.get 요청을 하자마자 바로 console.log를 찍었기 때문에 아직 응답을 받기 전이라서 pending이 뜬다.
function App() {
const fetchTodos = async() => {
const response = axios.get('http://localhost:3001/todos');
console.log('response', response);
}
useEffect (() => {
//db로부터 값을 가져오기
fetchTodos();
}, [])
....
따라서 await을 axios 앞에 적어줌으로써 데이터 요청 응답을 받을 때까지 기다리고, 작업이 완료되면 그 다음 줄로 넘어가 console.log를 찍어보면 데이터가 아래처럼 성공적으로 가져와진다.
function App() {
const fetchTodos = async() => {
const response = await axios.get('http://localhost:3001/todos');
console.log('response', response);
}
useEffect (() => {
//db로부터 값을 가져오기
fetchTodos();
}, [])
...
4. 서버에서 받은 데이터를 컴포넌트 안에서 쓰기
4-1. 데이터에 대한 state 만들기
const [todos, setTodos] = useState(null);
4-2. 서버에서 가져온 데이터와 연결하기
const fetchTodos = async() => {
const {data} = await axios.get('http://localhost:3001/todos');
setTodos(data);
}
아까 서버에서 가져온 데이터의 형태는 객체 형태로, 우리가 필요한 데이터는 'data'라는 key의 value 값으로 들어있다. 따라서 구조분해할당을 통해 data에 대한 값을 선언해주고, setTodos에 데이터를 설정해준다.
5. 서버에서 받은 데이터를 화면에 보여주기
5-1. UI 에 데이터 뿌려주기
이제 todos로 서버에서 받은 데이터를 사용할 수 있기때문에, 컴포넌트의 return 부분에 jsx 문법으로 UI를 만들어준다.
return (
<div>
{todos.map((item)=> {
return(
<div key={item.id}>
<h3>title: {item.title}</h3>
<p> id: {item.id}</p>
</div>
);
})}
</div>
);
전체코드
import axios from "axios";
import { useEffect, useState } from "react";
function App() {
const [todos, setTodos] = useState(null);
const fetchTodos = async() => {
const {data} = await axios.get('http://localhost:3001/todos');
console.log('response', data);
setTodos(data);
}
useEffect (() => {
//db로부터 값을 가져오기
fetchTodos();
}, [])
return (
<div>
{todos.map((item)=> {
return(
<div key={item.id}>
<h3>title: {item.title}</h3>
<p> id: {item.id}</p>
</div>
);
})}
</div>
);
}
export default App;
5-2. 에러 잡기
이렇게 코드를 짜고, 다시 새로고침을 해보면 아래처럼 에러가 나온다
WHY? 데이터를 요청하는 것은 처음 랜더링이 top -> bottom까지 한번 된 후에 발동하기 때문에, return 부분에 있는 todos에는 데이터가 없을 수 있다는 것이다.
SOLUTION 이를 방지하기 위해서 옵셔널 체이닝을 넣어줌으로써 todos가 있는지 확인한 후, map을 돌릴 수 있게 한다.
//? 붙이기
return (
<div>
{todos?.map((item)=> {
return(
<div key={item.id}>
<h3>title: {item.title}</h3>
<p> id: {item.id}</p>
</div>
);
})}
</div>
);
참고
fetch/then 과 axios/then, axios/async/await 을 사용한 데이터 가져오기
'부트캠프 개발일지 2023-2024 > React 리액트' 카테고리의 다른 글
[9주차] 리액트심화: Axios VS Fetch (0) | 2023.11.28 |
---|---|
[9주차] 리액트심화: 비동기 통신 axios(post, delete,patch) 하기 (0) | 2023.11.28 |
[9주차] 리액트심화: HTTP, URL, 상태코드 (1) | 2023.11.28 |
[9주차] 리액트심화: json server + 스탠다드 내용 업데이트 (0) | 2023.11.28 |
[9주차] 리액트심화: Redux Toolkit, Redux Devtools (0) | 2023.11.28 |