라우터
보통 일반적인 웹 애플리케이션에서는 URI로 요청을 보내면 서버에서 HTML 파일을 만들어서 내려주기 때문에
페이지 새로고침이 일어나게된다. SPA는 클라이언트 측에서 화면을 렌더링하는 소스를 가지고 렌더링을 하기 때문에
새로고침이 일어나지 않으면서 화면의 변경이 이루어 진다. SPA 에서 URI에 따라 화면을 그려주는 것이다.
이 역할을 라우터가 한다.
React 는 라우터 기능을 지원하지 않기 때문에 라우팅을 하기 위한 라이브러리를 설치해주어야 한다.
npm install react-router-dom --save
npm install cross-env --save-dev
react-router-dom 은 라우팅을 할 수 있게 해주는 라이브러리 이고
cross-env는 프로젝트에서 NODE_PATH를 사용할수 있게 해주어
import 할 때 상대경로를 사용해야 하는데 설정에 따라 절대경로를 사용 할 수 있게 해주는 라이브러리 이다.
cross-env 설정
컴포넌트 import시에 절대경로를 사용할수있도록 package.json 파일의 scripts 를 수정한다
(../pages/page1 -> page/page1 이런식으로 import 할수 있게 해준다.)
"scripts": {
"start": "cross-env NODE_PATH=src react-scripts start",
"build": "cross-env NODE_PATH=src react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
라우터 기본설정
src/client/App.js
컴포넌트를 특정 경로에 맵핑할 App.js 파일 생성
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>
리액트 라우터
</div>
);
}
}
export default App;
src/client/Root.js
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import App from 'client/App';
const Root = () => (
<BrowserRouter>
<App/>
</BrowserRouter>
);
export default Root;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Root from 'client/Root';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<Root />, document.getElementById('root'));
registerServiceWorker();
pages 디렉토리 index.js 작성
src/pages/index.js
디렉토리의 index.js는 컴포넌트 import시에 각각 개별로 import 하지 않고 비구조화 할당으로 경로 한군데서 컴포넌트를 import 할 수 있게 해준다.
ex) import { Main, Page1, Pages, Basic } from 'pages';
export { default as Main } from './Main';
export { default as Pages } from './Pages';
export { default as Page1 } from './Page1';
export { default as Page2 } from './Page2';
export { default as Page3 } from './Page3';
export { default as Basic } from './Basic';
라우터 경로 맵핑
src/client/App.js
처음에 생성한 App.js에 컴포넌트와 경로들을 맵핑해준다.
import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import Menu from '../components/Menu';
import { Main, Page1, Pages, Basic } from 'pages';
class App extends Component {
render() {
return (
<div>
<h2>React Tutorial</h2>
<Menu />
<Route exact path="/" component={Main}/>
<Switch>
<Route path="/page1/:name" component={Page1}/>
<Route path="/page1" component={Page1}/>
</Switch>
<Route path="/Pages" component={Pages}/>
<Route path="/basic" component={Basic}/>
</div>
);
}
}
export default App;
<Route> 컴포넌트에 path 는 경로 component는 맵핑할 컴포넌트를 지정해준다.
exact 속성은 경로가 정확히 일치해야만 라우터가 맵핑된 컴포넌트를 렌더링한다.
<Switch> 컴포넌트는 같은경로에 조건부로 라우팅을 하는 컴포넌트이다.
위 소스에서는 Switch컴포넌트에서 url경로로 파라미터가 전달된 경우와 전달되지 않은 경우를 구분하고 있다.
먼저 조건에 일치하는 컴포넌트만 렌더링 되기 때문에 조건이 들어가는 경로를 더 위에 작성해주어야 한다.
라우터 링크
src/components/Menu.js
SPA는 페이지가 새로고침되지 않으면서 경로를 이동해야 한다. a 태그를 사용해 링크를 걸면 페이지가 새로고침 되면서 페이지를 이동하기 때문에
Link 라는 컴포넌트를 사용해 경로를 링크한다.
import React from 'react';
import { Link } from 'react-router-dom';
const Menu = () => {
return (
<div>
<h3>메뉴</h3>
<ul>
<li><Link to="/">메인</Link></li>
<li><Link to="/Basic">기본 기능</Link></li>
<li><Link to="/Page1">라우터</Link></li>
<li><Link to="/Page1/BruceLee?name=BruceLee">라우터에 파라미터 전달</Link></li>
<li><Link to="/Pages">라우터 중첩</Link></li>
</ul>
<hr/>
</div>
);
};
export default Menu;
라우터에 파라미터 전달 / 값 사용, 쿼리스트링 사용
src/pages/page1.js
라우터 경로 맵핑시에 <Route path="/page1/:name" component={Page1}/> name이라는 변수명으로 파라미터를 전달받을수 있게 맵핑후
파라미터를 받아서 값을 사용 할 수 있다. 기존의 get 방식으로 쿼리스트링을 전달하는 방식으로 파라미터를 전달 할 수도 있다.
page1에 라우팅하면서 name 이라는 변수명 으로 'BruceLee' 전달, 쿼리스트링으로 name=BruceLee 전달하는 라우터 링크
<Link to="/Page1/BruceLee?name=BruceLee">라우터에 파라미터 전달</Link>
import React from 'react';
import queryString from 'query-string';
const Page1 = ({location, match}) => {
const query = queryString.parse(location.search);
const name = query.name
return (
<div>
<h2>
Page1
<br/>라우트에서 name이라는 명칭으로 지정한 params : {match.params.name}
<br/>url 쿼리로 전달받은 name : {name}
</h2>
</div>
);
};
export default Page1;
match.params 에는 <Route path="/page1/:name"> 로 전달한 값을 꺼내 사용 할 수있고
url에서 ?name=BruceLee 라고 전달한
쿼리스트링의 경우에는 location.search 객체에서 꺼내 직접 파싱을 해도 되고 쿼리스트링 파싱 모듈을 사용해도 된다.
npm install query-string --save
쿼리스트링을 파싱하는 모듈을 설치하고 값을 파싱하는 코드
const query = queryString.parse(location.search);
const name = query.name
라우터 중첩 / NavLink 컴포넌트
src/pages/pages.js
라우터 컴포넌트 안에서 현재의 페이지를 유지하면서 페이지 내부에서 다른화면을 보여주는 라우터 중첩도 가능하다.
match.url 로 현재 라우터가 보여주고 있는 페이지를 유지하면서 그 하위 경로로 보여줄 컴포넌트들을 맵핑 시켜 라우터를 중첩한다.
NavLink 컴포넌트는 페이지가 라우팅되어 보여지고 있을 때 그 페이지를 링크하는 컴포넌트에 스타일을 줄 수 있는 컴포넌트이다.
activeStyle 이라는 속성으로 페이지가 보여지고 있을때 활성화시킬 style 을 주어 사용한다.
import React from 'react';
import { NavLink, Route } from 'react-router-dom';
import { Page1, Page2, Page3 } from 'pages';
const Pages = ({match}) => {
const activeStyle={color: 'red', fontSize: '16px'}
return (
<div>
<h2>Post List</h2>
<ul>
<li><NavLink to={`${match.url}/page1`} activeStyle={activeStyle}>페이지1</NavLink></li>
<li><NavLink to={`${match.url}/page2`} activeStyle={activeStyle}>페이지2</NavLink></li>
<li><NavLink to={`${match.url}/page3`} activeStyle={activeStyle}>페이지3</NavLink></li>
</ul>
<Route exact path={match.url} render={()=>(<h3>라우터 중첩</h3>)}/>
<Route path={`${match.url}/page1`} component={Page1}/>
<Route path={`${match.url}/page2`} component={Page2}/>
<Route path={`${match.url}/page3`} component={Page3}/>
</div>
);
};
export default Pages;
참고
'React.js' 카테고리의 다른 글
컴포넌트 최적화 shouldComponentUpdate (0) | 2018.07.30 |
---|---|
리액트 리스트 CRUD (0) | 2018.07.12 |
리액트 폼 바인딩 React Form Binding (0) | 2018.07.05 |
리액트 리스트 렌더링 React List Rendering (0) | 2018.07.03 |
리액트 라이프사이클 React Life Cycle (0) | 2018.07.02 |