관리 메뉴

사과하는 제라스

13장. 리액트 라우터로 SPA 개발하기 본문

코테이토 동아리/[코테이토]React 스터디 5기

13장. 리액트 라우터로 SPA 개발하기

Xerath(제라스) 2023. 2. 3. 14:18

목차

    728x90
    반응형

    - 라우팅이란?

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

     

    - 라우팅 시스템 라이브러리 종류

    1) react-router

    2) Next.js

    3) react-location, rakkas 등등

    - SPA(Single Page Application)이란?

    "하나의 페이지로 이루어진 애플리케이션"

    -> HTML을 한번만 받아와서 웹 애플리케이션을 실행시킨 후, 이후에는 필요한 데이터만 받아와서 화면에 업데이트하는 것.

     

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

    - 기본 사용법

    1) <BowserRouter>를 src/index.js 파일에서 감싸주면 됨.

    2) <Routes> 컴포넌트 내에 <Route path="addressRule" element={showingComponent JSX} />

    로 트리 틀을 잡음.

     

    - 타 페이지로 이동하는 Link 버튼 설정

    <Link to="/about">소개</Link>

    - URL 파라미터

    : useParams라는 Hook을 쓰면 URL 파라미터를 객체 형태로 하여 조회 가능함.

    //App.js
    import { Route, Routes } from "react-router-dom";
    import About from "./pages/About";
    import Home from "./pages/Home";
    import Profile from "./pages/Profile";
    import Articles from "./pages/Articles";
    import Article from "./pages/Article";
    import Layout from "./Layout";
    import NotFound from "./pages/NotFound";
    import Login from "./pages/Login";
    import MyPage from "./pages/MyPage";
    
    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;
    import { useParams } from "react-router-dom";
    
    const data = {
      xerath: {
        name: "윤동주",
        descriptiong: "리액트 개발을 하고 싶은 꿈꾸사",
      },
      gildong: {
        name: "홍길동",
        description: "고전 소설 홍길돌전의 주인공",
      },
    };
    
    const Profile = () => {
      const params = useParams();
      const profile = data[params.username]; //이걸로 key-value 객체에서 원하는 값을 찾는구나!
    
      return (
        <div>
          <h1>사용자 프로필</h1>
          {profile ? (
            <div>
              <h2>{profile.name}</h2>
              <p>{profile.description}</p>
            </div>
          ) : (
            <p>존재하지 않는 프로필입니다.</p>
          )}
        </div>
      );
    };
    
    export default Profile;

    - 쿼리스트링

     

    1. useLocation

    : 이걸 쓰면

    pathname: 쿼리 스트링을 제외한 현재 주소의 경로

    search: 맨 앞의 ? 문자를 포함한 쿼리스트링 값

    hash: 주소의 # 문자열 뒤의 값

    state: 페이지로 이동할 때 임의로 넣을 수 있는 상태 값

    key: location 객체의 고유값. initial key는 default.

    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;

     

    2. useSearchParams

    -> params에 대한 useState 기능 같은 거라고 보면 됨.

    import { useSearchParams } from "react-router-dom";
    
    const About = () => {
      const [searchParams, setSearchParams] = useSearchParams({
        mode: 1,
        detail: "true",
      });
      const detail = searchParams.get("detail");
      const mode = searchParams.get("mode");
    
      const onToggleDetail = () => {
        setSearchParams({ mode, detail: detail === "true" ? false : true });
      };
    
      const onToggleMode = () => {
        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={onToggleMode}>Toggle Mode</button>
        </div>
      );
    };
    
    export default About;

     

    - 중첩된 라우트

    1. <Outlet /> 사용 -> 상위 컴포넌트를 가져다가 보여줄 수 있음.

    2. 상위 컴포넌트에 element 설정 -><Route> 상위 컴포넌트에서 하위 컴포넌트들에 뿌려줌.

    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 />} /> //이 부분이 Oulet을 통해 나타남.
          </Route>
          <Route path="/login" element={<Login />} />
          <Route path="/mypage" element={<MyPage />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      );
    };
    import { Outlet, NavLink } 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
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
            to={`articles/${id}`}
          >
            게시글 {id}
          </NavLink>
        </li>
      );
    };
    
    export default Articles;

    - useNavigate

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

    import { Outlet, useNavigate } from "react-router-dom";
    
    const Layout = () => {
      const navigate = useNavigate();
    
      const goBack = () => {
        navigate(-1);
      };
    
      const goArticles = () => {
        navigate("/articles", { replace: true }); //replace 옵션 사용 시 페이지 이동할 때 현재 페이지를 페이지 기록에 남기지 않음.
      };
      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;

    - NavLink

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

    isActive를 boolean값으로 전달받음.

    import { Outlet, NavLink } 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
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
            to={`articles/${id}`}
          >
            게시글 {id}
          </NavLink>
        </li>
      );
    };
    
    export default Articles;

    - *을 이용해서 Not Found 페이지 구현

    import { Route, Routes } from "react-router-dom";
    import About from "./pages/About";
    import Home from "./pages/Home";
    import Profile from "./pages/Profile";
    import Articles from "./pages/Articles";
    import Article from "./pages/Article";
    import Layout from "./Layout";
    import NotFound from "./pages/NotFound";
    import Login from "./pages/Login";
    import MyPage from "./pages/MyPage";
    
    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 />} /> //이런 식으로 해주면 매칭되지 않는 주소들은 모두 NotFound 컴포넌트를 보여줌.
        </Routes>
      );
    };
    
    export default App;

    - Navigate

    : 컴포넌트를 화면에 보여주는 순간 다른 페이지로 이동을 하고 싶을 때 사용하는 컴포넌트(페이지를 리다이렉트하고 싶을 때 씀!)

    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;

     

    728x90
    반응형