본문 바로가기
리액트(React)

리액트로 뉴스뷰어 만들어 보기(4)

by 즐거운코딩 2023. 6. 6.
반응형

리액트 라우터로 뉴스 카테고리 페이지 만들어 봅니다.

라우터를 사용하기 위해 리액트-라우터를 설치합니다.

>npm i react-router-dom 

리액트 라우터를 적용할 때 만들어야 할 페이지는 단 하나입니다. src 디렉터리에 pages라는 디렉터리를 생성하고, 그 안에 NewsPage.js 파일을 다음과 같이 만듭니다.

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

const NewsPage = () => {
  const params = useParams();
  // 카테고리가 선택되지 않았으면 기본값 all 사용
  const category = params.category || 'all';

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

export default NewsPage;

현재 선택된 category 값을 URL 파라미터를 통해 사용할 것이므로 Category 컴포넌트에서 현재 선택된 카테고리 값을 알려 줄 필요도 없고, onSelect 함수를 바로 전달해 줄 필요도 없습니다.

App.js 에 Route 를 다음과 같이 작성합니다.

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

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

export default App;

경로에 category URL 파라미터가 없어도 NewsPage 컴포넌트를 보여줘야 하고, category가 있어도 NewsPage를 보여줘야 하기 때문에 Route 컴포넌트를 두번 사용합니다.

 

그리고 Categories에서 기존의 onSelect 함수를 호출하여 카테고리를 선택하고, 선택된 카테고리에 다른 스타일을 주는 기능을 NavLink로 대체해봅니다. div, a, button, input 처럼 일반 HTML 요소가 아닌 특정 컴포넌트에 styled-components를 사용할 때는

styled(컴포넌트이름)' 과 같은 형식을 사용합니다.

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

const categories = [
 ...
];

const CategoriesBlock = styled.div`
 ...
`;

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: #3c9db;
    }
  }

  & + & {
    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;

NavLinK는 isActive라는 상태정보가 들어있어서 콜백으로 삼항연산을 통해 문자열로 출력 할 수 있습니다.

NavLink로 만들어진 Category 컴포넌트에 to 값은 "/카테고리이름" 으로 설정해 주었습니다.  그리고 카테고리 중에서 전체보기이 경우는 예외적으로 "/all" 대신에 "/" 로 설정했습니다.

반응형