본문 바로가기
  • soldonii's devlog
Javascript 공부/React

withRouting()으로 프로퍼티 전달하기

by soldonii 2019. 12. 16.

*Udemy의 "Complete React Developer in 2020" 강의에서 학습한 내용을 정리한 포스팅입니다.

*자바스크립트와 리액트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)


1. withRouting

앞선 글에서 props는 Route 컴포넌트의 프로퍼티로 전달된 첫번째 컴포넌트만 받을 수 있었다. 현재 만들던 앱의 구조를 살펴보면, Route 컴포넌트는 HomePage 컴포넌트를 렌더링하고 있다. 따라서 HomePage 컴포넌트 내부에서는 match, history, location 같은 객체를 이용할 수 있지만 HomePage 컴포넌트 내부에서 리턴하고 있는 Directory 컴포넌트, MenuItem 컴포넌트 등은 위 객체를 전달받지 못한다.

 

이를 해결할 방법은 위에서부터 전달받은 props를 계속 아래의 컴포넌트에게 props로 전달해주는 것이다. 하지만 이는 Bad Practice이다. 왜냐하면 예를 들어 최하층의 컴포넌트에서만 이 props가 필요한 경우에, 중간의 매개 컴포넌트들은 해당 props가 필요하지 않음에도 불구하고 단순히 아래로 props를 전달하기 위해 해당 props를 계속 받아야 하기 때문이다. 이를 Props Tunnelling(Drilling)이라고 부른다.

 

다행히 react-router-dom 라이브러리에는 이를 해결할 기능이 내장되어 있는데, withRouter가 바로 그것이다. withRouter는 고차함수로, 하나의 컴포넌트를 인자로 받아 해당 컴포넌트에 withRouter의 기능을 내장시킨 후, 변환된 새로운 컴포넌트를 리턴시킨다. 예시로 살펴보자.

import React from 'react';
import { WithRouter } from 'react-router-dom';
import './menu-item.styles.scss';

const MenuItem = ({ title, imageUrl, size, history }) => ( // history 이용 가능하다.
  <div className={`${size} menu-item`} onClick={() => history.push()}>
    <div className="background-image" style={{
      backgroundImage: `url(${imageUrl})`
    }}
    />
    <div className="content">
      <h1 className="title">{title.toUpperCase()}</h1>
      <span className="subtitle">SHOP NOW</span>
    </div>
  </div>
)

export default WithRouter(MenuItem); // WithRouter로 컴포넌트를 묶어준다.

현재 구조는 <Route> 가 렌더링시킬 HomePage 컴포넌트 → Directory 컴포넌트 → MenuItem 컴포넌트 구조로 이뤄져있다. 따라서 원래는 match, history, location 등의 객체는 Route가 렌더링시키는 HomePage 컴포넌트 내부에서만 사용할 수 있는 상황이다. 

 

MenuItem 컴포넌트 내부에 WithRouter 객체를 import 한 후, export할 MenuItem 컴포넌트를 WithRouter로 감싸주면 match, history, location 객체에 접근할 수 있는 힘을 가진 MenuItem이 export된다. 이후에는 자유자재로 해당 객체를 이용할 수 있다.

 

2. (번외) 리액트에 svg 파일 import 하기

import { ReactComponent as Logo } from '../../assets/crown.svg';

리액트에서 svg 파일을 import할 때는 위의 특수한 문법을 사용한다.

댓글