// Data Fetching & HTTP Request
- 서버에서 데이터를 가져오거나, 서버에 데이터를 보내는 과정
- Fetch API 나 Axios를 사용하여 HTTP 요청을 수행할 수 있다.
- 리액트는 JavaScript 라이브러리이기 때문에, 자바스크립트의 방식을 그대로 사용한다.
- https://sorrel012.tistory.com/346 참고
// Fetch API
방법 1. then 체인 사용하기
fetch('url')
.then(response => {
return response.json();
})
.then(data => {
...
})
- then() 메서드를 연결하여 Promise 가 resolve 될 때 실행될 콜백 함수를 설정한다.
방법 2. async / await 사용하기
async function 함수명() {
const response명 = await fetch('url');
const data명 = await response.json();
...
}
함수명();
- 응답과 응답의 data를 await를 활용하여 받는다.
- 방법 1 보다 많이 쓰인다.
// Error 처리
try {
const response명 = await fetch('url');
if (!response명.ok) {
throw new Error('Failed to fetch places');
}
const data명 = await response명.json();
} catch (error) {
...
}
- response.ok 를 통해 응답을 성공적으로 받았는지 확인할 수 있는데, 만약 그렇지 않았다면 error 를 발생시킬 수 있다.
- 발생한 에러는 catch()로 처리할 수 있다.
import { useCallback, useEffect, useRef, useState } from 'react';
import Places from './components/Places.jsx';
import Modal from './components/Modal.jsx';
import DeleteConfirmation from './components/DeleteConfirmation.jsx';
import logoImg from './assets/logo.png';
import AvailablePlaces from './components/AvailablePlaces.jsx';
import { fetchUserPlaces, updateUserPlaces } from './http.js';
import Error from './components/Error.jsx';
function App() {
const selectedPlace = useRef();
const [userPlaces, setUserPlaces] = useState([]);
const [isFetching, setIsFetching] = useState(false);
const [error, setError] = useState();
const [errorUpdatingPlaces, setErrorUpdatingPlaces] = useState();
const [modalIsOpen, setModalIsOpen] = useState(false);
async function fetchPlaces() {
setIsFetching(true);
try {
const places = await fetchUserPlaces();
setUserPlaces(places);
} catch (error) {
setError({ message: error.message || 'Failed to fetch user places' });
}
setIsFetching(false);
}
useEffect(() => {
fetchPlaces();
}, []);
function handleStartRemovePlace(place) {
setModalIsOpen(true);
selectedPlace.current = place;
}
function handleStopRemovePlace() {
setModalIsOpen(false);
}
async function handleSelectPlace(selectedPlace) {
setUserPlaces((prevPickedPlaces) => {
if (!prevPickedPlaces) {
prevPickedPlaces = [];
}
if (prevPickedPlaces.some((place) => place.id === selectedPlace.id)) {
return prevPickedPlaces;
}
return [selectedPlace, ...prevPickedPlaces];
});
try {
await updateUserPlaces([selectedPlace, ...userPlaces]);
} catch (error) {
setUserPlaces(userPlaces);
setErrorUpdatingPlaces({
message: error.message || 'Failed to update places.',
});
}
}
const handleRemovePlace = useCallback(
async function handleRemovePlace() {
setUserPlaces((prevPickedPlaces) =>
prevPickedPlaces.filter(
(place) => place.id !== selectedPlace.current.id,
),
);
try {
await updateUserPlaces(
userPlaces.filter((place) => place.id !== selectedPlace.current.id),
);
} catch (error) {
setUserPlaces(userPlaces);
setErrorUpdatingPlaces({
message: error.message || 'Failed to delete',
});
}
setModalIsOpen(false);
},
[userPlaces],
);
function handleError() {
setErrorUpdatingPlaces(null);
}
return (
<>
<Modal open={errorUpdatingPlaces} onClose={handleError}>
{errorUpdatingPlaces && (
<Error
title="An error occurred!"
message={errorUpdatingPlaces.message}
onConfirm={handleError}
/>
)}
</Modal>
<Modal open={modalIsOpen} onClose={handleStopRemovePlace}>
<DeleteConfirmation
onCancel={handleStopRemovePlace}
onConfirm={handleRemovePlace}
/>
</Modal>
<header>
<img src={logoImg} alt="Stylized globe" />
<h1>PlacePicker</h1>
<p>
Create your personal collection of places you would like to visit or
you have visited.
</p>
</header>
<main>
{error && <Error title="An error occured!" message={error.message} />}
<Places
title="I'd like to visit ..."
fallbackText="Select the places you would like to visit below."
isLoading={isFetching}
loadingText="Fetching your places..."
places={userPlaces}
onSelectPlace={handleStartRemovePlace}
/>
<AvailablePlaces onSelectPlace={handleSelectPlace} />
</main>
</>
);
}
export default App;
// Axios
- https://sorrel012.tistory.com/290 참고
'클라이언트 > React' 카테고리의 다른 글
[리액트(React)] 리덕스(Redux) (0) | 2024.02.14 |
---|---|
[리액트(React)] Custom Hook (0) | 2024.02.09 |
[리액트(React)] Class-based Component (0) | 2024.02.07 |
[리액트(React)] Reducer, useReducer(Hook) (0) | 2024.02.02 |
[리액트(React)] 포탈(Portal) (1) | 2024.02.01 |