본문 바로가기
  • 장원익 기술블로그
📺 Front End/-- react & redux & nextjs

[React Router & styled-components] 실전에서 withRouter를 사용하기(3) :: withRouter의 location props 로 상태 변경하기

by Wonit 2020. 10. 7.

해당 시리즈는 총 3부작으로 나누어져 있습니다.

  1. 실전에서 withRouter를 사용하기(1) :: Router 구성하기
  2. 실전에서 withRouter를 사용하기(2) :: styled-components를 활용하여 스타일링 적용하기
  3. 실전에서 withRouter를 사용하기(3) :: withRouter 사용하기

해당 시리즈에는 react의 styled-components에 대한 코드가 나올 것이다.

 

지금 우리는 withRouter에 대해서 알아보는 과정이므로 styled-components에 대해서 잘 모르는 사람은 그냥 css 적용을 js 안에서 수행하구나~ 정도만 이해하고 넘어가도록 하자.

 

하지만 개인적인 추천으로 styled-components에 대해서 모르는 사람은 정말 멋지고 쿨한 기능이므로 해당 블로그의
styled-components 카테고리에서 사용 방법 및 Styled-Components의 철학에 대해서 조금 봐보는 것을 매우 강력히 추천한다.

결과적으로 우리는

이런 웹 사이트의 상단 header를 구현할 것이고, 클릭하는 위치마다 border-bottom의 색이 변경될 것이다.


지난 시간 우리는 styled-components로 스타일링한 컴포넌트에 current props를 줘서 클릭한 링크만 border-bottom의 색을 바꿔보았다.

오늘은 드디어 withRouter를 사용하여 해당 링크에 갔을 시에만 border-bottom 속성을 주는 코드를 구현할 시간이다.

 

다시 한 번 withRouter

react-roter-dom 이나 styled-components를 사용하느라 원래의 목적인 withRouter를 까먹었을 수도 있으니 다시 한 번 withRouter를 상기시켜보자.

withRouter는 Router가 아닌 컴포넌트에게 Router 특성을 부여한다.
Router는 location, match, history를 사용한다.

그 중에 우리는 location을 사용할 것이다.

location

location 객체에는 현재 페이지의 정보를 갖는다.

  • pathname : 현재 페이지의 경로명
  • search : 현재 페이지의 query String
  • hash : 현재 페이지의 Hash

match

<Route path>와 URL이 매칭한 정보가 담겨있다.

  • path : 라우터에 정의된 path

  • url : 실제 클라이언트로 부터 요청된 url path

  • isExact : true일 경우 전체 경로가 완전히 매칭될 경우에만 요청을 실행

  • params : url path로 전달된 파라미터 객체

    history

  • 브라우저의 history와 유사하며, 스택에 현재까지 이동한 url의 경로들이 담겨있는 형태로 주소를 임의로 변경하거나 되돌아갈 수 있다.

  • length : 전체 스택의 길이

  • action : 최근 수행된 action

  • push : 새로운 경로를 history로 푸시하여 페이지 이동

  • goBack() : 이전 페이지로 이동

  • goForward() : 앞 페이지로 이동

 

코딩하기

이제 withRouter를 적용해서 우리가 지난 시간에 짰던 코드를 마무리해보자.

 

withRouter를 export하기

우선 우리는 지금까지 Header.js 파일에서 export를 Header를 수행했다.

export const Header = () => {...};

하지만 우리는 Header.js라는 파일이 다른 곳에서 쓰일 때 라우터 처럼쓰이길 원하므로
withRouter를 반환해야한다.


그리고 react-router-domwithRouter를 추가시키는 것도 잊지말자.

import { withRouter } from "react-router-dom";

export default withRouter();

 

withRouter의 props로 location의 pathname을 적용시키기

다음과 같은 형식의 분해구조를 통해 location의 pathname을 사용할 수 있게 하자.

export default withRouter( ({ location: { pathname} }) => {...} );

 

current props에 조건 부여하기

current={pathname === "/"}과 같은 형식으로 props를 주게 될 것인데, 이를 이용해서 style를 조건부 렌더링하게 된다.

import React from 'react';
import { Link, withRouter } from "react-router-dom";
import styled from "styled-components";

const SLink = styled(Link)`
  padding: 15px 20px;
  color: ${props => props.current ? "#0050FF" : "gray"};
  border-bottom: 4px solid 
  ${props => props.current ? "#0050FF" : "transparent"};
`;

const SItem = styled.li`
  text-align: center;
`;

const SList = styled.ul`
    display: flex;
`;

const SHeader = styled.header`
  display: flex;
  padding: 0px 30px; 
  width: 100%;
  height: 55px;
  align-items: center;
  background-color: rgba(245, 245, 245, 0.8);
  z-index: 10;
  box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.2);
  margin-bottom: 20px;
  ${SList}:first-child {
    margin-right: auto;
  }
`;

export default withRouter(({ location: { pathname } }) => (
  <SHeader>
    <SList>
      <SItem>
        <SLink current={false} to="/">DESIGN BASE</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/about"} to="/about">소개</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/course-design"} to="/course-design">디자인 강좌</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/course-coding"} to="/course-coding">웹코딩 강좌</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/bookmark"} to="/bookmark">북마크</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/meetup"} to="/meetup">밋업</SLink>
      </SItem>
    </SList>
    <SList>
      <SItem>
        <SLink current={pathname === "/contact"} to="/contact">문의하기</SLink>
      </SItem>
    </SList>
  </SHeader>
));

그럼 우리가 예상한 대로 withRouter를 이용하여 현재 위치해 있는 링크에 따라 변화하는 코드를 작성할 수 있게 된다.

 

댓글