본문 바로가기

Libraries/React

[React] Routing (4) 리스트 페이지에서 게시글 클릭 시 상세 페이지 연결하기 (게시판 리스트 조회, useParams, useNavigate, Route, Routes, id 동적 라우팅)

728x90

   

목차

(router 설정까지 이미 다 하신분은 10번 부터 보시면 됩니다)

1. App.jsx, App.css 기본 구성하기
2. src/pages 내에 폴더 구성하기
3. <BrowserRouter> import 하기
4. 4개의 페이지 import 하기
5. <Routes> import 하기
6. <Route> import 하기
7. /list 경로 추가하기
8. 나머지 페이지 경로 추가하기 
9. 리스트페이지와 상세페이지 마크업하기
10. App.jsx에서 path 속성 처리하기
11. id 별로 상세페이지 다르게 나오게 하기
12. 리스트페이지에서 리스트박스를 클릭하면 해당 상세페이지로 이동하게 하기 

 

 

 

리스트페이지에서 게시글 클릭 시 상세페이지로 연결되는 router를 구현해보자!

구글링을 해봐도 기존의 블로그 주인들 코드들과 합쳐져서 이해할 수 없는 글이 많아서
필자는 뻘짓을 (굉장히) 많이 했기에...ㅎ (사실 매우 간단한거였는데...억울...)

누구나 이해하기 쉽도록 (본인들 코드에 적용하기 쉽도록)
맨처음 상태부터 만들어서 최대한 핵심만 써보고자 한다.
매우 친절하고 구체적으로 써서 이것만 봐도  이해 무조건 된다. 솔직히 ㅎㅎ

 

 


 

 

 만들 예제의 완성본 

 

 

 

 

 1. App.jsx와 App.css에서 불필요한 내용들을 삭제하고 최소한의 내용만 추가해둔 상태이다. 

 

 App.jsx 

import './App.css';

function App() {
  return (
    <div className="App">
      <h2>App.jsx</h2>
      
    </div>
  );
}

export default App;

 

 App.css 

.App{
  padding: 20px;
}

 

 

 

 

 2. src/pages 폴더 안에 필요한 페이지(파일)들을 만든다. 

 

 

 

 Home.jsx  (메인페이지)

const Home = () => {
  return <div>
    <h1>Home</h1>
    <p>이곳은 홈입니다.</p>
  </div>
}

export default Home;

 

 

 List.jsx  (리스트 페이지) 

const List = () => {
  return <div>
    <h1>List</h1>
    <p>이곳은 리스트페이지입니다.</p>
  </div>
}

export default List;

 

 

 Detail.jsx   (상세페이지)

const Detail = () => {
  return <div>
    <h1>Detail</h1>
    <p>이곳은 상세페이지입니다.</p>
  </div>
}

export default Detail;

 

 

 

 3. <BrowserRouter> 컴포넌트를 import해서 사용하기 

 

(1) <BrowserRouter>를 import한다.

(2) 브라우저의 url과 앱을 연결하는 기능을 하는 <BrowserRouter> 컴포넌트로 App 컴포넌트가 return하는 부분을 감싸준다. 

 

 

 App.jsx 

import "./App.css";
import { BrowserRouter } from "react-router-dom"; // BrowserRouter를 import한다.

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 4. 4개의 페이지 컴포넌트들을 import 한다. 

 

 App.jsx 

import "./App.css";
import { BrowserRouter } from "react-router-dom";
import Home from './pages/Home/Home'
import List from './pages/List/List'
import Detail from './pages/Detail/Detail'

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 5. <Routes> 컴포넌트를 import해서 사용하기 

 

브라우저의 url이 바뀌게 되면 어떤 컴포넌트를 렌더링해서 페이지 역할을 하게 할 것인지 결정하기 위해서 바뀔 부분을 <Routes> 컴포넌트로 감싸준다.

 

 App.jsx 

import "./App.css";
import { BrowserRouter, Routes } from "react-router-dom";
import Home from "./pages/Home/Home";
import List from "./pages/List/List";
import Detail from "./pages/Detail/Detail";

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
        <Routes>

          
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 6. <Route> 컴포넌트를 import해서 사용하기 

 

<Route> 컴포넌트는 실질적으로 url 경로와 컴포넌트를 맵핑시켜준다.

path와 element를 작성하기 → "path가 index를 가리키고 있으면, <Home>컴포넌트를 렌더링해라."

url 경로가 "/" (아무것도 없는거랑 똑같은 경로)이기 때문에, Route.Provider가 전달받은 <Home> 컴포넌트를 url을 맵핑시켜서 정상적으로 렌더링한다.

 

 App.jsx 

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home/Home";
import List from "./pages/List/List";
import Detail from "./pages/Detail/Detail";

function App() {
  return (
<BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
        <Routes>
          <Route path='/' element={<Home />}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 

 7. /list 경로 추가해보기 

 

 App.jsx 

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home/Home";
import List from "./pages/List/List";
import Detail from "./pages/Detail/Detail";

function App() {
  return (
<BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
        <Routes>
          <Route path='/' element={<Home />}/>
          <Route path='/list' element={<List />}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

http://localhost:5173/list 로 주소창에 입력해본다.

 

 

여기서 <h2>App.jsx</h2>가 노출되는 이유는,

페이지가 바뀔 때 변화하는 부분은 <Routes>안에 있는 부분만 변화하게 설계했기 때문에 바깥 쪽 부분은 그대로 유지가 되기 때문이다.

즉, 페이지가 바뀌어도 항상 보여져야되는 요소를 작성해야한다면 <Routes> 컴포넌트 바깥쪽으로 빼서 작성을 하면된다. (바깥 쪽에 빼서 작성한 것은 어떤 페이지에서도 다 나타나게끔 할 수 있는 것이다. 예를들어 헤더나 푸터 같은 것들)

 

 

 

 8. 나머지 페이지들도 경로 추가하기 

 

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home/Home";
import List from "./pages/List/List";
import Detail from "./pages/Detail/Detail";

function App() {
  return (
<BrowserRouter>
      <div className="App">
        <h2>App.jsx</h2>
        <Routes>
          <Route path='/' element={<Home />}/>
          <Route path='/list' element={<List />}/>
          <Route path='/detail' element={<Detail />}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 

 9. 리스트페이지와 상세페이지 마크업하기 (CSS코드는 간단해서 생략) 

 

 List.jsx  (리스트 페이지) 

import "./List.css";

const List = () => {
  const dummyList = [
    {
      id: 1,
      title: "1번 게시글",
    },
    {
      id: 2,
      title: "2번 게시글",
    },
    {
      id: 3,
      title: "3번 게시글",
    },
    {
      id: 4,
      title: "4번 게시글",
    },
    {
      id: 5,
      title: "5번 게시글",
    },
  ];

  return (
    <div>
      <h1>List</h1>
      <p>이곳은 리스트페이지입니다.</p>
      <div className="list-container">
        {dummyList.map((it) => (
          <div key={it.id}>
            <div className="list-box">{it.title}</div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default List;

 

dummyList로 데이터리스트를 만들고, 데이터에 map을 돌려서 리스트 박스가 차례대로 뜨게 만든다.

 

 

 

 Detail.jsx  (상세 페이지) 

import "./Detail.css";

const Detail = () => {
  const dummyDetail = [
    {
      id: 1,
      title: "1번 게시글",
      content: "1번 내용입니다."
    },
    {
      id: 2,
      title: "2번 게시글",
      content: "2번 내용입니다."
    },
    {
      id: 3,
      title: "3번 게시글",
      content: "3번 내용입니다."
    },
    {
      id: 4,
      title: "4번 게시글",
      content: "4번 내용입니다."
    },
    {
      id: 5,
      title: "5번 게시글",
      content: "5번 내용입니다."
    },
  ];

  const targetData = dummyDetail.find(
    (it) => it.id === 1
  );

  return (
    <div>
      <h1>Detail</h1>
      <p>이곳은 상세페이지입니다.</p>
      <div className="detail-container">

            <h2 className="detail-title">{targetData.title}</h2>
            <div className="detail-content">{targetData.content}</div>
          </div>

      </div>

  );
};

export default Detail;

 

dummyDetail로 데이터리스트를 만들고, 데이터에 find 메서드를 써서 id가 1번인 데이터만 뜨게 만든다. (일단은 임의로 1번만 뜨게 만드는 것) 

 

 

 

 

 10. Path Variable을 사용하기 위해 App.jsx에서 path 속성을 처리해준다. 

 

<Route path='/detail/:id' element={<Detail />}/>

 

id에 따라서 상세 페이지가 다르게 나오게 구성해야한다.

예컨대 detail/1처럼 1이라는 동적인 값을 처리하게 하기 위해서는 Path Variable을 사용해야한다.

Path Variable을 사용하려면 route에서 path 속성에 별도로 처리를 해줘야한다.

사용방법은, id로 쓸 부분을 /:id 로 적고, 뒤에 있는 id라는 이름으로 뒤에 있는 값을 전달하면 된다.

 

 

 App.jsx 

import "./App.css";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "./pages/Home/Home";
import List from "./pages/List/List";
import Detail from "./pages/Detail/Detail";

function App() {
  return (
<BrowserRouter>
      <div className="App">
        <Routes>
          <Route path='/' element={<Home />}/>
          <Route path='/list' element={<List />}/>
          <Route path='/detail/:id' element={<Detail />}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 

 11.  id 별로 상세페이지 다르게 나오게 하기 

 

Path Variable 꺼내서 사용하기 → 상세페이지에서 useParams를 사용하면 된다.

 

<순서>

(1) import { useParams } from "react-router-dom";
// useParams를 import한다.

(2) const {id} = useParams();
// useParams를 이용하면, 전달 받아서 들어오는 Path Variable들을 모아서 객체로 갖다주게 되는데,
// Path Variable를 id라고 부르기로 약속했기 때문에, id로 꺼내와야한다.

(3) const targetData = dummyDetail.find( (it) => parseInt(it.id) === parseInt(id) );
// find 메서드를 사용해서 해당 id와 일치하는 데이터를 찾아온다.

 

 

 Detail.jsx  (상세 페이지) 

import { useParams } from "react-router-dom"; // (1) useParams를 import한다.
import "./Detail.css";



const Detail = () => {

  const {id} = useParams(); // (2) id로 꺼내오기
  
  const dummyDetail = [
    {
      id: 1,
      title: "1번 게시글",
      content: "1번 내용입니다."
    },
    {
      id: 2,
      title: "2번 게시글",
      content: "2번 내용입니다."
    },
    {
      id: 3,
      title: "3번 게시글",
      content: "3번 내용입니다."
    },
    {
      id: 4,
      title: "4번 게시글",
      content: "4번 내용입니다."
    },
    {
      id: 5,
      title: "5번 게시글",
      content: "5번 내용입니다."
    },
  ];


// (3) find 메서드를 사용해서 해당 id와 일치하는 데이터를 찾아온다.
  const targetData = dummyDetail.find(  
    (it) => parseInt(it.id) === parseInt(id)
  );

  return (
    <div>
      <h1>Detail</h1>
      <p>이곳은 상세페이지입니다.</p>
      <div className="detail-container">

            <h2 className="detail-title">{targetData.title}</h2>
            <div className="detail-content">{targetData.content}</div>
          </div>

      </div>

  );
};

export default Detail;

 

 

여기까지 잘 따라왔으면, 주소창에 id를 다르게 칠때마다, 각 id에 해당하는 상세페이지가 등장하게된다.

 

 

 

 

 12. 리스트 페이지에서 리스트 박스를 클릭하면 해당 상세페이지로 이동하게 한다. 

 

마지막으로 리스트페이지에서 1번 게시글을 클릭하면 1번 상세페이지로 가게끔 하는 것만 하면 된다.

 

<순서>

(1) import { useNavigate } from "react-router-dom"; 
// useNavigate를 import한다.

(2) <div className="list-box" onClick={() => { navigate(`/detail/${it.id}`); }}>{it.title}</div> 
// 리스트 박스에 해당하는 <div>에 클릭 이벤트를 달아서 경로를 설정해준다.

 

 

 List.jsx  (리스트 페이지)

import { useNavigate } from "react-router-dom"; // (1) useNavigate를 import한다. 
import "./List.css";

const List = () => {

  const navigate = useNavigate(); 

  const dummyList = [
    {
      id: 1,
      title: "1번 게시글",
    },
    {
      id: 2,
      title: "2번 게시글",
    },
    {
      id: 3,
      title: "3번 게시글",
    },
    {
      id: 4,
      title: "4번 게시글",
    },
    {
      id: 5,
      title: "5번 게시글",
    },
  ];

  return (
    <div>
      <h1>List</h1>
      <p>이곳은 리스트페이지입니다.</p>
      <div className="list-container">
        {dummyList.map((it) => ( // (2) 클릭 이벤트에 경로 설정해주기
          <div key={it.id}>
            <div className="list-box" onClick={() => { navigate(`/detail/${it.id}`); }}>{it.title}</div> 
          </div>
        ))}
      </div>
    </div>
  );
};

export default List;

 

 

 

 완성본 

 

 

 

 


 

 

 Router  시리즈 몰아보기 (기초부터 심화까지) 

 

 

 1. Router의 개념 

 

https://dev-ini.tistory.com/81

 

[React] Routing (1) 개념, SPA & CSR

Routing에 대해서 알아보자! Routing Router [위키백과] 어떤 네트워크 내에서 통신 데이터를 보낼 경로를 선택하는 일련의 과정 데이터의 경로를 실시간으로 지정해주는 역할을 하는 무언가 Routing 경

dev-ini.tistory.com

 

 

 2. Router 설치 및 사용방법 

 

https://dev-ini.tistory.com/82

 

[React] Routing (2) Router 설치 및 사용방법 완벽 정리

Router를 설치하는 방법과 사용 방법을 알아보자! 이 게시글을 보기 전에 봐야하는 게시글들 1. 개발환경: CRA (개발 환경 설정은 아래의 게시글을 참고해주세요!) https://dev-ini.tistory.com/83 [CRA] CRA(Crea

dev-ini.tistory.com

 

 

 3. useParams, QueryString, useNavigate 사용방법 

 

https://dev-ini.tistory.com/84

 

[React] Routing (3) Path Variable(useParams), Query String(useSearchParams), Page Moving(useNavigate)

목차 1. Path Variable - useParams 2. Query String - useSearchParams 3. Page Moving - useNavigate 이 게시글을 보기 전에 봐야하는 게시글들 1. Router의 개념 (Router의 개념과 SPA와 CSR에 대한 설명이 있습니다.) https://dev-i

dev-ini.tistory.com

 

728x90