[React] axios 예제 (+ NavLink, usePromise 커스텀 Hook 만들기)

겨레·2024년 12월 5일

[React] 리액트 스터디

목록 보기
80/95

기본 사용법

우선 axios 라이브러리를 설치해야 한다.

import React, { useEffect, useState } from "react";
import axios from "axios";

const App = () => {
  const [data, setData] = useState([]); // 데이터 상태
  const [loading, setLoading] = useState(false); // 로딩 상태
  const [error, setError] = useState(null); // 에러 상태

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true); // 로딩 시작
      setError(null); // 이전 에러 초기화

      try {
        const response = await axios.get(
          "https://jsonplaceholder.typicode.com/posts"
        );
        setData(response.data); // 데이터 저장
      } catch (err) {
        setError(err.message); // 에러 저장
      } finally {
        setLoading(false); // 로딩 끝
      }
    };

    fetchData();
  }, []); // 컴포넌트 마운트 시 1회 실행

  if (loading) return <p>Loading...</p>; // 로딩 중 표시
  if (error) return <p>Error: {error}</p>; // 에러 표시

  return (
    <div>
      <h1>Data</h1>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default App;

1. Axios 사용

  • axios.get(url)로 데이터를 가져온다.
  • 반환된 데이터를 response.data로 읽는다.

2. useEffect 사용

  • 컴포넌트가 처음 렌더링될 때 API를 호출한다.

3. 상태 관리

  • data
    : API 호출 결과를 저장
  • loading
    : 데이터를 가져오는 동안 로딩 상태를 관리함.
  • error
    : API 호출 중 에러가 발생하면 이를 저장.

4. 로딩/에러 처리

  • 로딩 중에는 "Loading..."을 표시하고, 에러가 발생하면 에러 메시지를 표시함.


확장 예제

  • POST 요청
axios.post('https://jsonplaceholder.typicode.com/posts', {
  title: 'New Post',
  body: 'This is the content of the post',
  userId: 1,
});

  • 쿼리 파라미터 전달
axios.get('https://jsonplaceholder.typicode.com/posts', {
  params: { userId: 1 },
});

  • 에러 핸들링 추가
try {
  const response = await axios.get(url);
} catch (err) {
  if (axios.isAxiosError(err)) {
    console.error('Axios error:', err.message);
  } else {
    console.error('Unknown error:', err);
  }
}

📍 NavLink
React 또는 다른 프론트엔드 프레임워크에서 사용되는 네비게이션 컴포넌트로 사용자는 애플리케이션 내에서 라우트를 이동하며 네비게이션 링크의 활성 상태(active state)를 관리할 수 있다.

  • React Router에서 제공하는 컴포넌트로, 네비게이션 링크를 생성할 때 사용됨.
  • 특정 경로가 활성화되었을 때(현재 경로와 링크 경로가 일치할 때) 자동으로 CSS 클래스나 스타일을 적용할 수 있음.
  • NavLink는 현재 경로와 매칭되면 기본적으로 active라는 클래스를 적용함. 이를 통해 활성화된 링크를 시각적으로 구분할 수 있음.
  • className 또는 style 속성에 콜백 함수를 전달하여 동적으로 스타일을 지정할 수 있음.
  • NavLink 주요 속성으로는 to, className, style, end, children이 있다.

📍 NavLink 사용법
React Router 라이브러리의 일부로 NavLink를 사용하려면 React Router를 설치해야 함.

npm install react-router-dom

✅ NavLink 주요 속성
✔ to ⇒ 이동할 경로를 설정

<NavLink to="/home">Home</NavLink>

✔ className ⇒ 활성화 상태에 따라 동적으로 클래스를 적용

<NavLink 
  to="/about" 
  className={({ isActive }) => (isActive ? "active-link" : "inactive-link")}
>
  About
</NavLink>

✔ style ⇒ 활성화 상태에 따라 동적으로 인라인 스타일을 지정

<NavLink 
  to="/contact" 
  style={({ isActive }) => ({ color: isActive ? "red" : "blue" })}
>
  Contact
</NavLink>

✔ end ⇒ 경로가 정확히 일치할 때만 활성화 상태로 간주

<NavLink to="/home" end>
  Home
</NavLink>

✔ children ⇒ 링크 내부에 렌더링할 콘텐츠를 설정(텍스트, 아이콘 등을 포함할 수 있음)




  • 예제

    • 먼저 React Router를 사용하기 위해서는 React 버전 16.8 이상이어야 하고 라이브러리 설치 후, 애플리케이션의 루트 컴포넌트를 BrowserRouter로 감싸야 함.

      // 기본 설정 예제
      import React from 'react';
      import ReactDOM from 'react-dom';
      import { BrowserRouter } from 'react-router-dom';
      import App from './App';
      
      ReactDOM.render(
      <BrowserRouter>
        <App />
      </BrowserRouter>,
      document.getElementById('root')
      );

    • NavLink를 사용한 예제

      import React from 'react';
      import { NavLink } from 'react-router-dom';
      
      function Navigation() {
       return (
         <nav>
           <NavLink to="/" end>Home</NavLink>
           <NavLink to="/about">About</NavLink>
           <NavLink to="/contact">Contact</NavLink>
         </nav>
       );
      }
      
      export default Navigation;



  • 또 다른 예제
import React from 'react';
import { BrowserRouter as Router, Routes, Route, NavLink } from 'react-router-dom';

function App() {
  return (
    <Router>
      <nav>
        <NavLink 
          to="/" 
          className={({ isActive }) => (isActive ? "active-link" : "")}
          style={({ isActive }) => ({ fontWeight: isActive ? "bold" : "normal" })}
          end
        >
          Home
        </NavLink>
        <NavLink to="/about">About</NavLink>
        <NavLink to="/contact">Contact</NavLink>
      </nav>
      <Routes>
        <Route path="/" element={<h1>Home Page</h1>} />
        <Route path="/about" element={<h1>About Page</h1>} />
        <Route path="/contact" element={<h1>Contact Page</h1>} />
      </Routes>
    </Router>
  );
}

export default App;

usePromise 커스텀 Hook 만들기

📍 usePromise
React에서 비동기 작업(특히 Promise) 커스텀 훅

  • 비동기 로직(예: API 호출, 데이터 처리)을 컴포넌트에 직접 작성하면 코드가 복잡해질 수 있는데, usePromise를 사용하면 보다 깔끔하게 처리하고, 상태 관리(로딩, 성공, 실패)가 용이하게 가능해짐.
  • usePromise 커스텀 훅을 만드는 예제

    • 로딩 상태
      : 데이터가 로드되는 동안 isLoading을 true로 설정
    • 결과
      : data 상태를 통해 성공적인 Promise 결과를 저장
    • 에러 처리
      : error 상태로 실패한 이유를 추적

import { useState, useEffect } from 'react';

function usePromise(promiseFn, deps = []) {
  const [data, setData] = useState(null);    // 데이터를 저장
  const [isLoading, setIsLoading] = useState(true);  // 로딩 상태
  const [error, setError] = useState(null);   // 에러 상태

  useEffect(() => {
    setIsLoading(true);  // 요청 시작 시 로딩 상태 설정
    setError(null);      // 에러 초기화

    promiseFn()
      .then((response) => {
        setData(response);  // 성공적으로 데이터를 받으면 상태에 저장
        setIsLoading(false);  // 로딩 끝
      })
      .catch((err) => {
        setError(err);  // 에러 발생 시 에러 상태에 저장
        setIsLoading(false);  // 로딩 끝
      });
  }, deps);  // 의존성 배열에 따라 리렌더링

  return { data, isLoading, error };
}

✔ promiseFn
Promise를 반환하는 함수

✔ deps
useEffect의 의존성 배열로, 이 값이 변경될 때마다 다시 promiseFn을 실행

✔ data
성공적으로 데이터를 받았을 때 저장되는 상태

✔ isLoading
데이터 로딩 중에는 true, 완료되면 false로 변경됨

✔ error
요청이 실패했을 때 발생한 에러를 저장하는 상태



  • usePromise 커스텀 훅 사용 데이터 로드 예시
import React, { useState } from 'react';
import usePromise from './usePromise';

// 예시 API 호출 함수 (Promise 반환)
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Fetched Data!");  // 성공적으로 데이터 받기
      // reject("Error!");  // 에러를 발생시키려면 주석을 풀기
    }, 2000);
  });
}

function App() {
  const { data, isLoading, error } = usePromise(fetchData, []); // usePromise 호출

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div>
      <h1>{data}</h1> {/* 데이터가 성공적으로 로드되면 화면에 표시 */}
    </div>
  );
}

export default App;

✔ fetchData 함수
Promise를 반환하는 비동기 작업으로 데이터가 로드되면 "Fetched Data!"가 반환됨.

✔ usePromise(fetchData, [])
fetchData를 호출하고, 결과를 data, isLoading, error로 관리함.
로딩 중에는 "Loading..." 메시지를 표시하고, 에러가 있으면 에러 메시지를, 데이터가 있으면 그 데이터를 화면에 출력함.

profile
호떡 신문지에서 개발자로 환생

0개의 댓글