본문 바로가기
Project/[클론 코딩] 뉴스 뷰어

[클론 코딩] 리액트 라우터 적용

by Bam_t 2022. 1. 3.
728x90

지난번에 카테고리까지 구현하면서 뉴스 뷰어 앱을 완성했습니다. 이번에는 카테고리마다 리액트 라우터로 SPA한 페이지를 만들어보겠습니다.

2021.12.11 - [Programming/React] - [React] 리액트 라우터

 

[React] 리액트 라우터

이번에는 리액트 라우터 라이브러리를 통해서 SPA가 적용되는 것을 간단하게 알아보려고 합니다. SPA에 대해서는 아래 링크 설명을 참조해주세요. 2021.12.09 - [Programming/CS] - SPA, Single Page Application..

bamtory29.tistory.com

2021.12.09 - [Programming/CS] - SPA, Single Page Application

 

SPA, Single Page Application

1. SPA SPA, Single Page Application은 하나의 페이지로 이루어진 웹 어플리케이션 또는 웹 페이지를 말하는 용어입니다. 그동안은 html을 배워오고 간단한 웹 사이트를 하나 만들면서 보통 여러개의 페이

bamtory29.tistory.com

 

우선 리액트 라우터를 설치해주세요.

yarn add react-router-dom

그런다음 라우터 사용을 위해 index.js 파일을 수정해주세요.

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

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

reportWebVitals();

1. 뉴스 뷰어 앱에 리액트 라우터 적용하기

기존 앱을 고쳐서 SPA 페이지를 만들어 보겠습니다. 우선 단일 화면을 위한 NewsPage 페이지입니다.

import React, {Fragment} from 'react';
import Categories from './components/Categories';
import NewsList from './components/NewsList';
import {useParams} from 'react-router-dom';

const NewsPage = ({match}) => {
    const params = useParams();
    const category = params.category || 'all';

    return (
        <Fragment>
            <Categories/>
            <NewsList category={category}/>
        </Fragment>
    );
};

export default NewsPage;

기존에 카테고리 이동을 위해서 Categories 컴포넌트로부터 선택된 카테고리나 onSelect 함수를 props로 전달했어야하는데, SPA 페이지에서는 url 파라미터로 현재 선택 카테고리 정보를 전달 받으므로 필요가 없어졌습니다.

useParams라는 것을 이용했는데 이것의 역할은 url로 부터 파라미터를 가져오는 역할을 합니다. 그래서 가져온 파라미터에 따라 카테고리를 결정하고 보여줄 뉴스를 정하게 됩니다.

App.js 함수의 내용을 지우고 다음과 같이 수정해주세요. 라우터로 단일 페이지를 구성하므로 NewsPage 컴포넌트만 보여주면 됩니다.

import React from 'react';
import {Route, Routes} from 'react-router-dom';
import NewsPage from './NewsPage';


const App = () => {
    return (
        <Routes>
            <Route path={"/"} element={<NewsPage/>}/>
            <Route path={"/:category"} element={<NewsPage/>}/>;
        </Routes>
    );
};

export default App;

"/"는 아무것도 선택되지 않은 혹은 전체 보기가 선택된 경우입니다. 그 외의 "/:category"는 카테고리 name을 받아서 url창에 따른 뉴스 정보를 표시해줍니다.

 

 

 

2. NavLink

이제 카테고리 선택에 따른 주소창과 뉴스를 보여주기 위해 Categories 컴포넌트에서 작업을 해보겠습니다. 우선 전체 코드입니다.

import React from 'react';
import styled from 'styled-components';
import {NavLink} from 'react-router-dom';

const categories = [
    {
        name: 'all',
        text: '전체보기',
    },
    {
        name: 'business',
        text: '비즈니스',
    },
    {
        name: 'entertainment',
        text: '엔터테인먼트',
    },
    {
        name: 'health',
        text: '건강',
    },
    {
        name: 'science',
        text: '과학',
    },
    {
        name: 'sports',
        text: '스포츠',
    },
    {
        name: 'technology',
        text: '기술',
    },
];

const CategoriesBlock = styled.div`
  display: flex;
  padding: 1rem;
  width: 768px;
  margin: 0 auto;
  @media screen and (max-width: 768px) {
    width: 100%;
    overflow-x: auto;
  }
`;

const Category = styled(NavLink)`
  font-size: 1.125rem;
  cursor: pointer;
  white-space: pre;
  text-decoration: none;
  color: inherit;
  padding-bottom: 0.25rem;

  &:hover {
    color: #495057;
  }

  &.active {
    font-weight: 600;
    border-bottom: 2px solid #22b8cf;
    color: #22b8cf;

    &:hover {
      color: #3bc9db;
    }
  }

  & + & {
    margin-left: 1rem;
  }
`;

const Categories = () => {
    return (
        <CategoriesBlock>
            {categories.map(c => (
                <Category key={c.name} className={({isActive}) => (isActive ? 'active' : undefined)}
                          to={c.name === 'all' ? '/' : `/${c.name}`}>
                    {c.text}
                </Category>
            ))}
        </CategoriesBlock>
    );
};

export default Categories;

 

const Category = styled(NavLink)`
  font-size: 1.125rem;
  cursor: pointer;
  white-space: pre;
  text-decoration: none;
  color: inherit;
  padding-bottom: 0.25rem;

  &:hover {
    color: #495057;
  }

  &.active {
    font-weight: 600;
    border-bottom: 2px solid #22b8cf;
    color: #22b8cf;

    &:hover {
      color: #3bc9db;
    }
  }

  & + & {
    margin-left: 1rem;
  }
`;

이 부분은 선택된 카테고리에 스타일을 주는 부분입니다. NavLink가 선택된 컴포넌트에 효과를 주도록 만들어줍니다.

 

const Categories = () => {
    return (
        <CategoriesBlock>
            {categories.map(c => (
                <Category key={c.name} className={({isActive}) => (isActive ? 'active' : undefined)}
                          to={c.name === 'all' ? '/' : `/${c.name}`}>
                    {c.text}
                </Category>
            ))}
        </CategoriesBlock>
    );
};

NavLink로 생성된 Category 컴포넌트가 변경되었습니다. active가 되면 to를 통해 해당 카테고리에 효과를 주도록 했습니다.

실행을 하면 다음처럼 주소창에 결과가 잘 나타나나요?


이렇게 두번째 클론 코딩 프로젝트인 뉴스 뷰어가 완성되었습니다.

728x90

댓글