본문 바로가기

WINK-(Web & App)/React.js 스터디

[2024 React.js 스터디] 김지나 #7주차

반응형

4장. API 연동하기

- 웹 애플리케이션을 만들 때, 데이터를 보존시키고 다른 사람들도 조회할 수 있게 하려면 서버를 만들고 서버의 API를 사용해서 데이터를 읽고 써야 함

 

1. API 연동의 기본

- 새 프로젝트 만들고 axios 라이브러리 설치

$ npx create-react-app api-integrate
$ cd api-integrate
$ yarn add axios

- axios를 사용해서 GET, PUT, POST, DELETE 등의 메서드로 API 요청 가능

- REST API를 사용할 때에는 하고 싶은 작업에 따라 다른 메서드로 요청할 수 있음

(GET: 데이터 조회, POST: 데이터 등록, PUT: 데이터 수정, DELETE: 데이터 제거)

 

- axios 사용법

import axios from 'axios';

axios.get('/users/1'); //사용하고 싶은 메서드 이름, 파라미터에는 API 주소

- axios.post()로 데이터를 등록할 때에는 두번째 파라미터에 등록하고자 하는 정보 기입

axios.post('/users', {
  username: 'blabla',
  name: 'blabla'
});

 

- useState와 useEffect로 데이터 로딩하기

- useState를 사용하여 요청 상태를 관리하고,  useEffect를 사용하여 컴포넌트가 렌더링되는 시점에 요청을 시작하는 작업

요청에 대한 상태를 관리할 때에는 1. 요청의 결과 2. 로딩 상태 3. 에러 세가지 상태를 관리해주어야 함.

//Users.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
  const [users, setUsers] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        // 요청이 시작 할 때에는 error 와 users 를 초기화하고
        setError(null);
        setUsers(null);
        // loading 상태를 true 로 바꿉니다.
        setLoading(true);
        const response = await axios.get(
          'https://jsonplaceholder.typicode.com/users'
        );
        setUsers(response.data); // 데이터는 response.data 안에 들어있습니다.
      } catch (e) {
        setError(e);
      }
      setLoading(false);
    };

    fetchUsers();
  }, []);

  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!users) return null;
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          {user.username} ({user.name})
        </li>
      ))}
    </ul>
  );
}

export default Users;

- useEffect에 첫번째 파라미터로 등록하는 함수에는 async를 사용할 수 없음. -> 함수 내부에서 async를 사용하는 새로운 함수를 선언

//App 렌더링
import React from 'react';
import Users from './Users';

function App() {
  return <Users />;
}

export default App;

새로고침 하면 로딩중...이라고 뜨는데.....너무빨리지나가서캡처를못하겠어요ㅜㅜㅜ

 

- 에러 발생 확인하기

- 에러 발생 확인을 위해 주소를 이상하게 바꿔보자!

 

- 버튼을 눌러서 API 재요청하기

- 버튼을 눌러서 API를 재요청하는 기능 구현해보기

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

function Users() {
  const [users, setUsers] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchUsers = async () => {
    try {
      // 요청이 시작 할 때에는 error 와 users 를 초기화하고
      setError(null);
      setUsers(null);
      // loading 상태를 true 로 바꿉니다.
      setLoading(true);
      const response = await axios.get(
        'https://jsonplaceholder.typicode.com/users'
      );
      setUsers(response.data); // 데이터는 response.data 안에 들어있습니다.
    } catch (e) {
      setError(e);
    }
    setLoading(false);
  };

  useEffect(() => {
    fetchUsers();
  }, []);

  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!users) return null;
  return (
    <>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            {user.username} ({user.name})
          </li>
        ))}
      </ul>
      <button onClick={fetchUsers}>다시 불러오기</button>
    </>
  );
}

export default Users;
//fetchUsers 함수를 바깥으로 꺼내주고 버튼 만들어서 함수 구현

다시 불러오기를 누르면 다시 로딩됨!!

 

React Router v6 튜토리얼

1. 라우팅이란?

: 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것

- 여러 페이지로 구성된 웹 애플리케이션을 만들 때 페이지별로 컴포넌트들을 분리해가면서 프로젝트를 관리하기 위해 필요한 것

- 리액트에서 라우트 시스템을 구축하는 방법에는 두 가지가 있음

1) 리액트 라우터: 가장 오래되고 많이 사용됨. 컴포넌트 기반으로 라우팅 시스템 설정 가능

2) Next.js: 다양한 기능 제공(라우팅 시스템, 최적화, 다국어 시스템 지원 ...), 파일 경로 기반 작동

- 리액트 라우터를 사용하겠습니다!!

 

2. 싱글 페이지 애플리케이션이란?

: 한 개의 페이지로 이루어진 애플리케이션

- 멀티 페이지 애플리케이션: 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고, 페이지를 로딩할 때마다 CSS, JS 등의 리소스를 전달받아 브라우저 화면에 보여줬었음. 사용자 인터랙션이 별로 없는 페이지들은 이 방식이 적합하지만, 사용자 인터랙션이 많고 다양한 정보를 제공하는 모던 웹 애플리케이션에서는 이 방식이 적합하지 않음 <- 서버 자원, 트래픽 소모가 큼

=> 뷰 렌더링을 사용자의 브라우저가 담당, 사용자 인터랙션이 발생하면 필요한 부분만 자바스크립트를 이용하여 업데이트하는 방식으로

이렇게 html은 한번만 받아오고 그 이후부터는 필요한 데이터만 받아와서 화면에 업데이트 해주는 것이 싱글 페이지 애플리케이션

- 기술적으로는 한 페이지지만 사용자는 여러 개가 있는 것처럼 느낌

 

3. 리액트 라우터 적용 및 기본 사용법

 

- 프로젝트 생성 및 라이브러리 설치

$ yarn create react-app router-tutorial

 

- 리액트 라우터 라이브러리 설치

$ cd router-tutorial
$ yarn add react-router-dom

 

- 프로젝트에 라우터 적용

- 프로젝트에 리액트 라우터를 적용할 때에는 src/index.js 파일에서 react-router-dom에 내장되어 있는 BrowserRouter 컴포넌트를 사용하여 감싸면 됨. 웹 애플리케이션에 HTML5의 History API를 사용하여 새 페이지를 불러오지 않고도 주소 변경, 현재 주소 경로 관련 정보를 리액트 컴포넌트에서 사용 가능

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

 

- 페이지 컴포넌트 만들기

// src/pages/Home.js
const Home = () => {
  return (
    <div>
      <h1>홈</h1>
      <p>가장 먼저 보여지는 페이지입니다.</p>
    </div>
  );
};

export default Home;

// src/pages/About.js
const About = () => {
  return (
    <div>
      <h1>소개</h1>
      <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
    </div>
  );
};

export default About;

 

- Route 컴포넌트로 특정 경로에 원하는 컴포넌트 보여주기

<Route path="주소규칙" element={보여 줄 컴포넌트 JSX} /> //Route 컴포넌트 사용 방법

- Route 컴포넌트는 Routes 컴포넌트 내부에서 사용되어야 함

import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
};

export default App;

처음에 렌더링이 안되길래 머지>??했는데 App 코드에 BrowserRouter 태그가 없더라구용...썼더니 뜨긴 했는데 확실히 이거 땜에 안 떴던건지는 모르겠습니다!!ㅠ

 

- Link 컴포넌트를 사용하여 다른 페이지로 이동하는 링크 보여주기

- 원래 링크를 보여줄 때는 a 태그를 사용하지만 리액트 라우터를 사용할 때는 바로 a태그를 쓰면 안됨!! a 태그를 클릭할 때는 페이지를 새로 불러오기 때문

-> Link 컴포넌트 사용해야함 (여기서도 a태그가 사용되긴 하지만 페이지를 새로 불러오는걸 막고 History API를 통해 브라우저 주소 경로만 바꿈)

<Link to="경로">링크 이름</Link> //사용방법
import { Link } from 'react-router-dom';

const Home = () => {
  return (
    <div>
      <h1>홈</h1>
      <p>가장 먼저 보여지는 페이지입니다.</p>
      <Link to="/about">소개</Link>
    </div>
  );
};

export default Home;
//Home.js 수정

소개 링크를 누르면 이동돼요!!

 

4. URL 파라미터와 쿼리스트링

- URL 파라미터: 주소의 경로에 유동적인 값을 넣는 형태(ID 또는 이름을 사용하여 특정 데이터를 조회할 때)

- 쿼리 스트링: 주소의 뒷부분에 ?문자열 이후에 key=value로 값을 정의하며 &로 구분하는 형태(데이터 조회에 필요한 옵션을 전달할 때)

 

- URL 파라미터

// src/pages/Profile.js
import { useParams } from 'react-router-dom';

const data = {
  velopert: {
    name: '김민준',
    description: '리액트를 좋아하는 개발자',
  },
  gildong: {
    name: '홍길동',
    description: '고전 소설 홍길동전의 주인공',
  },
};

const Profile = () => {
  const params = useParams();
  const profile = data[params.username];

  return (
    <div>
      <h1>사용자 프로필</h1>
      {profile ? (
        <div>
          <h2>{profile.name}</h2>
          <p>{profile.description}</p>
        </div>
      ) : (
        <p>존재하지 않는 프로필입니다.</p>
      )}
    </div>
  );
};

export default Profile;

- useParams Hook을 사용하여 객체 형태로 조회 가능

- URL 파라미터의 이름은 라우트 설정을 할 때 Route 컴포넌트의 path props를 통하여 설정

//App.js
import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
    </Routes>
  );
};

export default App;

- URL 파라미터는 경로에 :를 사용하여 설정

// src/pages/Home.js
import { Link } from 'react-router-dom';

const Home = () => {
  return (
    <div>
      <h1>홈</h1>
      <p>가장 먼저 보여지는 페이지입니다.</p>
      <ul>
        <li>
          <Link to="/about">소개</Link>
        </li>
        <li>
          <Link to="/profiles/velopert">velopert의 프로필</Link>
        </li>
        <li>
          <Link to="/profiles/gildong">gildong의 프로필</Link>
        </li>
        <li>
          <Link to="/profiles/void">존재하지 않는 프로필</Link>
        </li>
      </ul>
    </div>
  );
};

export default Home;

프로필 링크를 누르면 각 프로필 페이지로 이동합니다!!

 

- 쿼리스트링

- 쿼리스트링을 사용할 때에는 Route 컴포넌트를 사용할 때 별도로 설정할 게 없음!

//About.js
import { useLocation } from 'react-router-dom';

const About = () => {
  const location = useLocation();

  return (
    <div>
      <h1>소개</h1>
      <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
      <p>쿼리스트링: {location.search}</p>
    </div>
  );
};

export default About;

- useLocation Hook 사용. location 객체를 반환하며 현재 사용자가 보고있는 페이지의 정보를 지니고 있음

pathname 현재 주소의 경로 (쿼리 스트링 제외)
search 맨 앞의 ? 문자 포함한 쿼리스트링 값
hash 주소의 # 문자열 뒤의 값
state 페이지로 이동할 때 임의로 넣을 수 있는 상태 값
key location 객체의 고유 값

- 쿼리스트링은 location.search 값을 통해 조회 가능

- 주소창에 http://localhost:3000/about?detail=true&mode=1 입력!

- 여기서 앞에 있는 ?를 지우고 & 문자열로 분리하 뒤 key와 value를 파싱하는 작업을 해야 함

ㄴ 이 작업은 보통 npm에서 qs 또는 querystring 패키지를 설치해서 처리할 수 있음

ㄴ 너무 번거롭다,,,하지만 리액트 라우터 v6부터 useSearchParams Hook을 통해서 쿼리스트링을 쉽게 다룰 수 있음!!

/About.js
import { useSearchParams } from 'react-router-dom';

const About = () => {
  const [searchParams, setSearchParams] = useSearchParams();
  const detail = searchParams.get('detail');
  const mode = searchParams.get('mode');

  const onToggleDetail = () => {
    setSearchParams({ mode, detail: detail === 'true' ? false : true });
  };

  const onIncreaseMode = () => {
    const nextMode = mode === null ? 1 : parseInt(mode) + 1;
    setSearchParams({ mode: nextMode, detail });
  };

  return (
    <div>
      <h1>소개</h1>
      <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
      <p>detail: {detail}</p>
      <p>mode: {mode}</p>
      <button onClick={onToggleDetail}>Toggle detail</button>
      <button onClick={onIncreaseMode}>mode + 1</button>
    </div>
  );
};

export default About;

- useSearchParams는 배열 타입의 값을 반환하며 첫번째 원소는 쿼리파라미터를 조회하거나 수정하는 메소드들이 담긴 객체를 반환

- get 메서드를 통해 특정 쿼리파라미터 조회 가능 (쿼리파라미터가 존재하지 않는다면 null로 조회됨)

- set 메서드를 통해 특정 쿼리파라미터 업데이트 가능

- 두번째 원소는 쿼리파라미터를 객체형태로 업데이트할 수 있는 함수를 반환

- 주의!!! 쿼리파라미터를 조회할 때 값은 무조건 문자열 타입임!!!!

 

5. 중첩된 라우트

//Articles.js
import { Link } from 'react-router-dom';

const Articles = () => {
  return (
    <ul>
      <li>
        <Link to="/articles/1">게시글 1</Link>
      </li>
      <li>
        <Link to="/articles/2">게시글 2</Link>
      </li>
      <li>
        <Link to="/articles/3">게시글 3</Link>
      </li>
    </ul>
  );
};

export default Articles;
//Article.js
import { useParams } from 'react-router-dom';

const Article = () => {
  const { id } = useParams();
  return (
    <div>
      <h2>게시글 {id}</h2>
    </div>
  );
};

export default Article;
//App.js
import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
      <Route path="/articles" element={<Articles />} />
      <Route path="/articles/:id" element={<Article />} />
    </Routes>
  );
};

export default App;
//Home에 게시글 목록 페이지로 가는 링크 추가

게시글 목록을 누르면 게시글 링크로 이동

- 게시글 목록 페이지에서 게시글을 열었을 때, 게시글의 하단에 목록이 보이게 해보자!

- 기존 방식으로 구현한다면 ArticleList 컴포넌트를 따로 만들어서 각 페이지 컴포넌트에서 사용해야 함.

-> 중첩된 라우트를 사용한다면 좀 더 나은 방식으로 구현 가능

//App.js
import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
    </Routes>
  );
};

export default App;

- Articles 컴포넌트에서 Outlet 컴포넌트 사용. Route의 children으로 들어가는 JSX 엘리먼트를 보여주는 역할

//Articles.js
import { Link, Outlet } from 'react-router-dom';

const Articles = () => {
  return (
    <div>
      <Outlet />
      <ul>
        <li>
          <Link to="/articles/1">게시글 1</Link>
        </li>
        <li>
          <Link to="/articles/2">게시글 2</Link>
        </li>
        <li>
          <Link to="/articles/3">게시글 3</Link>
        </li>
      </ul>
    </div>
  );
};

export default Articles;

- outlet 컴포넌트가 사용된 자리에 중첩된 라우트가 보여짐

어랏...제건 왜 이렂죠..ㅜㅜㅜㅜ

 

이렇게 떠야 하는 것 가탕요....

 

- 공통 레이아웃 컴포넌트

- Home, About, Profile 페이지에서 상단에 헤더를 보여줘야 하는 상황을 가정해보자 

- Header 컴포넌트를 따로 만들어주고 각 페이지에서 재사용할 수도 있겠지만, 중첩된 라우트와 Outlet을 활용하면 컴포넌트를 한번만 사용해도 됨! 

//Layout.js
import { Outlet } from 'react-router-dom';

const Layout = () => {
  return (
    <div>
      <header style={{ background: 'lightgray', padding: 16, fontSize: 24 }}>
        Header
      </header>
      <main>
        <Outlet />
      </main>
    </div>
  );
};

export default Layout;
//App.js
import { Route, Routes } from 'react-router-dom';
import Layout from './Layout';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route element={<Layout />}>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Route>
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
    </Routes>
  );
};

export default App;

 

- index props

- index props는 path="/"와 동일한 의미를 가짐

import { Route, Routes } from 'react-router-dom';
import Layout from './Layout';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Route>
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
    </Routes>
  );
};

export default App;

- index prop은 상위 라우트의 경로와 일치하지만, 그 이후에 경로가 주어지지 않았을 때 보여지는 라우트를 설정할 때 사용

 

6. 리액트 라우터 부가기능

1) useNavigate

: Link 컴포넌트를 사용하지 않고 다른 페이지로 이동해야 하는 상황에 사용

import { Outlet, useNavigate } from 'react-router-dom';

const Layout = () => {
  const navigate = useNavigate();

  const goBack = () => {
    // 이전 페이지로 이동
    navigate(-1);
  };

  const goArticles = () => {
    // articles 경로로 이동
    navigate('/articles');
  };

  return (
    <div>
      <header style={{ background: 'lightgray', padding: 16, fontSize: 24 }}>
        <button onClick={goBack}>뒤로가기</button>
        <button onClick={goArticles}>게시글 목록</button>
      </header>
      <main>
        <Outlet />
      </main>
    </div>
  );
};

export default Layout;

.. 제 거에서는 안 떠서 강의에 있는 사진으로 대체합니다..ㅜㅜ

- navigate 함수를 사용할 때 파라미터가 숫자 타입이라면 앞으로 가거나 뒤로 감.

ex) navigate(-1): 한 번 뒤로 가기, navigate(-2): 두 번 뒤로 가기, navigate(1): 한 번 앞으로 가기

- replace: 페이지 이동할 때 현재 페이지를 페이지 기록에 남기지 않음

//goArticles 함수 수정
const goArticles = () => {
  navigate('/articles', { replace: true });
}

- Home -> About -> 게시글 목록 페이지 -> 뒤로가기로 이전 페이지로 이동: Home 페이지 나타남

 

2) NavLink

: 링크에서 사용하는 경로가 현재 라우트의 경로와 일치하는 경우 특정 스타일 또는 CSS 클래스를 적용하는 컴포넌트

- style 또는 className을 설정할 때 {isActive: boolean}을 파라미터로 전달받는 함수 타입의 값을 전달

import { NavLink, Outlet } from 'react-router-dom';

const Articles = () => {
  const activeStyle = {
    color: 'green',
    fontSize: 21,
  };

  return (
    <div>
      <Outlet />
      <ul>
        <li>
          <NavLink
            to="/articles/1"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 1
          </NavLink>
        </li>
        <li>
          <NavLink
            to="/articles/2"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 2
          </NavLink>
        </li>
        <li>
          <NavLink
            to="/articles/3"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 3
          </NavLink>
        </li>
      </ul>
    </div>
  );
};

export default Articles;

- 반복되는 코드 리팩토링

import { NavLink, Outlet } from 'react-router-dom';

const Articles = () => {
  return (
    <div>
      <Outlet />
      <ul>
        <ArticleItem id={1} />
        <ArticleItem id={2} />
        <ArticleItem id={3} />
      </ul>
    </div>
  );
};

const ArticleItem = ({ id }) => {
  const activeStyle = {
    color: 'green',
    fontSize: 21,
  };
  return (
    <li>
      <NavLink
        to={`/articles/${id}`}
        style={({ isActive }) => (isActive ? activeStyle : undefined)}
      >
        게시글 {id}
      </NavLink>
    </li>
  );
};

export default Articles;

 

3) NotFound 페이지 만들기

- 사전에 정의되지 않은 경로에 사용자가 진입했을 때 보여주는 페이지

//NotFound.js
const NotFound = () => {
  return (
    <div
      style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: 64,
        position: 'absolute',
        width: '100%',
        height: '100%',
      }}
    >
      404
    </div>
  );
};

export default NotFound;
//App.js
import { Route, Routes } from 'react-router-dom';
import Layout from './Layout';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import NotFound from './pages/NotFound';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Route>
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
};

export default App;

- *: 와일드카드 문자, 아무 텍스트나 매칭

 

4) Navigate 컴포넌트

- 화면에 보여주는 순간 다른 페이지로 이동을 하고 싶을 때 

- 페이지를 리다이렉트하고 싶을 때

//Login.js
const Login = () => {
  return <div>로그인 페이지</div>;
};

export default Login;
//Mypage.js
import { Navigate } from 'react-router-dom';

const MyPage = () => {
  const isLoggedIn = false;

  if (!isLoggedIn) {
    return <Navigate to="/login" replace={true} />;
  }

  return <div>마이 페이지</div>;
};

export default MyPage;
//App.js
import { Route, Routes } from 'react-router-dom';
import Layout from './Layout';
import About from './pages/About';
import Article from './pages/Article';
import Articles from './pages/Articles';
import Home from './pages/Home';
import Login from './pages/Login';
import MyPage from './pages/MyPage';
import NotFound from './pages/NotFound';
import Profile from './pages/Profile';

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Route>
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
      <Route path="/login" element={<Login />} />
      <Route path="/mypage" element={<MyPage />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
};

export default App;

 

반응형