React 입문(9) : React-Router(2) (last update: 2020.12.28.)

devpark·2020년 12월 28일
0

React.js & JavaScript

목록 보기
10/11

Notion의 Theory & Technique : React.js 페이지 바로가기


3-6. Reading Router parameters : Introduction

라우트의 경로에 특정 값을 대입하는 방법은 두 가지가 존재한다: 1. params 2. query를 사용하는 것이다. 먼저, route로 설정한 컴포넌트는 3가지의 props를 전달받게 된다:

  1. historypush, replace를 통해 다른 경로로 이동하거나 앞 뒤 페이지로 전환할 수 있다.
  2. location 객체는 현재 경로에 대한 정보를 지니고 있고, URL 쿼리(about?foo=bar 형식)의 정보도 가지고 있다. 참고로 location.pathname는 url의 path(즉 /foo 등의 경로)을 가리키고, location.search는 queryString의 정보를 가리킨다. 여기서 queryString이란 path이후의 ? 다음에 나오는 id=1과 같은 것을 의미한다.
  3. match 객체에는 어떤 route에 연결이 되었는지와 관련된 정보가 존재하고, param(/about/:name 형식) 정보가 존재한다.

URL 쿼리의 경우 컴포넌트 내에서 동적인 사용이 가능하고, params의 경우 사용 전에 반드시 route에서 지정을 해 주어야 한다.


3-6-1. Reading Router Parameters(1) : params

먼저, params를 사용할 때는 다음과 같이 코드를 작성하면 된다:

src/shared/App.js

class App extends Component{
	render(){
		return(
			<React.Fragment>
				// 정확한 경로로 root-path+/가 호출되었을 때 Home 컴포넌트를 노출한다.
				<Route exact path="/" component={ Home }/>
				// /about 경로로 접근할 시 About 컴포넌트를 노출한다.
				<Route path="/about" component={ About } />
				// /About 컴포넌트에 name이라는 params를 사용하는 것으로 설정한다.
				<Route path="/about/:name" component={ About }>
			</React.Fragment>
		);
	}
}
export default App;

위와 같이 URL의 params를 설정 할 때는 :foo의 형식으로 설정한다. 이렇게 선언해 주면 해당 컴포넌트에 foo라는 params가 생성된다.

src/pages/About.js

const About = ({ match }) => {
	return(
		<React.Fragment>
		// About Component의 본문 영역에 
		// name이라는 이름으로 선언한 params를 대입하여 확인한다.
			<h2>About { match.params.name }</h2>
		</React.Fragment>
	);
}
export default About;

About 컴포넌트에 name이라는 params를 생성하였고, 그 값은 위와 같이 해당 컴포넌트에 선언해 확인 할 수 있다.


하지만 위와 같이 코드를 작성하는 경우는 동일한 컴포넌트에 대입한 path가 복수이므로 /about 경로를 통해 접근하는 경우 /about에 할당된 컴포넌트인 { About }과 /about/:name에 할당된 컴포넌트 { About }이 한 화면에 노출되게 된다. 이러한 경우, 상기한 바와 같이 Route 선언문에 <Route exact path="/about" component={ About }/>과 같이 선언하여 정확한 경로로 접근하는 경우에만 해당 Component를 매치하거나, <Switch</Switch> 태그 내부에 해당 path를 매핑하여 매칭되는 첫 번째 Route만 노출하게 할 수 있다. 문법은 다음과 같다:

import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Home, About } from 'pages';
class App extends Component{
	render(){
		return(
			// 복수의 elements를 반환하도록 작성하였으므로 wrapping해 준다.
			<React.Fragment>
				// Root path/의 경로로 정확하게 접근하는 경우 Home 컴포넌트를 노출한다.
				<Route exact path="/" component={ Home } />
				// Switch 태그 내부에 매핑 route 작성을 시작한다.
				// 따라서 이 태그 내부에 위치하는 route들은 
				// 매칭되는 첫 번째 컴포넌트만 노출하고,
				// 하위의 결과는 화면단에 노출하지 않는다. 
				<Switch>
					// 따라서 /about/:name \의 경로로 접근하는 경우 첫 번째 route만 매칭한다.
					<Route path="/about/:name" component={ About } />
					<Route path="/about" component={ About } />
				</Switch>
			</React.Fragement>
		);
	}
}
export default App;

위의 태그 내부에 route를 매핑할 때에 주의할 점은, 중복되는 path를 통해 접근하는 경우 선언 순서에 따라 결과 값이 달라진다는 것이다. 사용자가 /about/:name의 경로로 접근하는 경우 name params를 가진 경로를 노출하고자 한다면 반드시 params가 포함된 Route 매핑을 전위에 작성해야 할 것이며, 이 params가 포함된 경로로 접근할 때에도 해당 /'about 통합 페이지를 노출하고자 한다면 /about 경로로 매핑된 route를 전위에 선언해 주면 된다.


3-6-2. Reading Router Parameters(2): URL Query

react-router v3에는 URL Query를 해석하여 객체로 생성하는 기능을 자체적으로 포함하고 있었으나, 쿼리를 parsing하는 여러가지 방식을 개발자가 직접 선택하여 사용할 수 있도록 현재의 버전은 더 이상 이를 내장하지 않는다. 따라서, URL Query를 해석하기 위해서는 별도의 방법을 사용하여야 한다. URL Query의 해석 및 객체 생성은 자체적으로 구현할 수도 있지만, 라이브러리를 사용하는 편이 훨씬 간편하다. 이는 아래의 커맨드를 통해 설치할 수 있다.

$ yarn add query-string

위와 같이 설치가 완료되면, 다음과 같이 코드를 작성한다.

src/pages.About.js

import React from 'react';
// queryString 라이브러리를 import한다.
import queryString from 'query-string';
// queryString 라이브러리의 var location, var match를 인자로 받는다. 
const About = ({ location, match }) => {
	// const로 query를 선언하며, 
	// 이는 queryString을 var location과 any search로 parsing한다(쪼갠다).
	const query = queryString.parse(location.search);
	// parsing한 값을 확인하기 위해 console에 log를 출력하도록 한다.
	console.log(query);
	return(
		<React.Fragment>
			<h2> About { match.params.name } </h2>
		</React.Fragement>
	);
};
export default About;

RESULT

이제 /about/cheetah?detail=true 경로로 접속하고 F12를 눌러 개발자 모드에서 콘솔을 열어보자. detail의 값인 true가 객체에 생성된 것을 확인 할 수 있다.


또한 이 값에 따른 Conditional Rendering도 가능하다. 문법은 다음과 같다:

import React from 'react';
// queryString을 해석해서 객체로 만들기 위한 라이브러리를 import한다.
import queryString from 'query-string';
// 인자로 var location, any match를 받으며 화살표 함수에 대입한다.
const About =({ location, match })=> {
	//queryString, 즉 path 이후의 값을 파싱하여 const query에 대입한다.
	// 참고로 parsing된 내용은 String의 형태로 반환된다.
	const query = queryString.parse(location.search);
	// query.detail이 string 형태로 받은 반환 값이 정확히 'true'라면
	// const detail에 query.detail 값을 대입한다.
	const detail = query.detail === 'true';
	// div에 대입할 스타일을 const로 선언한다.
	const bodyStyle= {
		margin: '12px',
		fontSize: '1.1rem',
		textAlign: 'center',
		backgroundColor: 'magenta',
		paddingTop: '2px',
		paddingBottom: '16px',
		color: 'white'
	}
	// console에 const query에 대입된 값을 출력한다. (확인용)
	console.log(query);
	return(
	<div style= { bodyStyle }>
		// params로 넘겨받은 name을 본문에 포함시켜 출력한다.
		<h2>About { match.params.name }</h2>
		// const detail이 true일 때와 false일 때를 분리하여
		// Ternary operator로 Conditional Rendering한다.
		{ detail ? 'detail is true!' : 'detail is false!' }
	</div>
	);
}
export default App;

단, URL Query를 사용할 때는 받아오는 값들이 전부 string(문자열)임에 주목하여야 한다. 비교 연산이 필요하거나 이에 따른 조건부 렌더링 구문 등이 필요한 경우에는 반드시 문자열 형태 또는, 알맞는 형변환을 거친 후 비교하여야 한다.


앱 내에서 다른 route로 이동할 때는, 페이지를 새로 고침 하는 <a href=""></a>가 아닌 리액트 라우터 내 Link 컴포넌트를 사용한다. 이 <Link></Link> 컴포넌트를 사용하면 페이지를 새로 불러오는 것을 막고, 원하는 route로 화면 전환을 할 수 있다.

예시 코드는 다음과 같다:

src/components/Menu.js

import React from 'react';
import { Link } from 'react-router-dom';
// 일반적인 Component 선언법과 동일하게 화살표 함수 내부에 작성 하고, export한다.
const Menu=()=>{
	return(
		<React.Fragment>
			<ul>
				<li><Link to="/">Home</Link></li>
				<li><Link to="/about">About</Link></li>
				<li><Link to="/about/foo?detail=true">About Foo True</Link></li>
			</ul>
			<hr/>
		</React.Fragment>
	);	
};
export default Menu;

src/shared/App.js

...
// *모든 path에 Menu를 노출하기 위하여 Switch 또는 exact를 사용하지 않음* 
<Route path="/" component={ Menu } />
...

RESULT

이 컴포넌트에 전달되는 props들은 컴포넌트 내부의 DOM에도 전달되므로, 일반 DOM 구성 요소에 설정하는 것 처럼 className, style 또는 onClick등의 이벤트 전달이 가능하다.


NavLink는 Link와 유사하나, 설정한 URL이 활성화되면 특정 스타일 또는 클래스를 지정할 수 있다.

src/components/Menu.js

import React from 'react';
import { NavLink } from 'react-router-dom';
const Menu=()=>{
	const activeStyle = {
		color: 'blue',
		fontSize: '1.2rem',
		fontStyle: 'italic'
	}
	return(
		<React.Fragment>
			<ul>
				<li><NavLink exact to="/" activeStyle={ activeStyle }>Home</NavLink></li>
				<li><NavLink exact to="/about" activeStyle={ activeStyle }>About :: Exact</NavLink></li>
				<li><NavLink to="/about/foo" activeStyle={ activeStyle }>About Foo:true</NavLink></li>
			</ul>
		</React.Fragment>
	);
}; 
export default Menu;

RESULT


profile
아! 응응애에요!

0개의 댓글