본문 바로가기

클라이언트/React
[리액트(React)] Data Fetching & HTTP Request

// Data Fetching & HTTP Request

- 서버에서 데이터를 가져오거나, 서버에 데이터를 보내는 과정

- Fetch API 나 Axios를 사용하여 HTTP 요청을 수행할 수 있다.

- 리액트는 JavaScript 라이브러리이기 때문에, 자바스크립트의 방식을 그대로 사용한다.

 https://sorrel012.tistory.com/346 참고

 

[자바스크립트(JavaScript)] API, Ajax

// API, Application Programming Interface - 컴퓨터가 여러 소프트웨어와 상호작용하거나 소통하는 모든 인터페이스를 의미 - 웹에서 사용하는 API > HTTP를 기반으로 하는 인터페이스인 WebAPI // Ajax - 비동기

sorrel012.tistory.com


// 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 참고

 

[뷰(Vue)] Axios, Form

// axios - HTTP 통신 오픈 소스 라이브러리 https://github.com/axios/axios GitHub - axios/axios: Promise based HTTP client for the browser and node.js Promise based HTTP client for the browser and node.js - GitHub - axios/axios: Promise based HTTP

sorrel012.tistory.com