Route를 들어가기 앞서 SPA를 다시 한번 알아보자
SPA?
Single Page Application의 약자로, 말 그대로 페이지가 1개인 애플리케이션이란 뜻이다.
전통적인 웹 어플리케이션의 구조는 여러 페이지로 구성되어 있다.
react-router는 써드파티 라이브러리로, 공식은 아니지만 가장 많이 사용되고 있는 라이브러리이다.
이 라이브러리는 클라이언트 사이드에서 이뤄지는 라우팅을 간단하게 해 준다.
react-router-dom
기본적으로
react-router-dom이 브라우저에서 사용되는 리액트 라우터이다.
import React from 'react';
import {Route} from 'react-router-dom';
import { Home, About } from 'pages';
const App = () => {
return (
<div>
<Route exact path = "/" component = {Home} />
<Route path = "/about" component = {About} />
</div>
);
}
라우트를 설정할 때는 Route 컴포넌트를 사용하고, 경로를 path 값으로 설정한다.
여기서 path는 주소를 나타내며, component는 해당 주소에 렌더링 될 페이지를 나타낸다.
여기서 조금 특이한 게 있다!
바로 exact 이게 붙어있으면 주어진 경로와 정확히 맞아떨어져야만 설정한 컴포넌트를 보여준다.
만약 exact 가 없다면 /about으로 이동하게 되더라도 "/about" 안에는 "/"가 있기 때문에
Home 화면도 같이 렌더링이 된다.
아니 그러면 만약 "/" 도 Home을 나타내게 하고 "/Home"도 Home을 나타나게는 못하나?
<Route exact path = {["/","/Home"]} component = {Home} />
당근 빠따로 가능하다! 위와 같이 사용하면!
그리고 index.js에서
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
document.getElementById("root")
);
BrowserRouter를 선언해준다.
그러면 준비 끝!
react-router-dom에서 파라미터는 안 되냐?
외않되?
라우트의 경로에 특정 값을 넣는 방법은 2가지가 있는데, params와 query를 사용하는 것이다!
라우트로 설정한 컴포넌트는, 3가지의 props를 전달받게 되는데,
- history : push , replace , goBack 등을 통해 다른 경로로 이동하거나 앞 뒤 페이지로 전환!
- location : 현재 경로에 대한 정보를 지니고 있고 URL 쿼리(/about? foo=bar 형식) 정보를 가짐!
- match : 어떤 라우트와 매칭인지 대한 정보가 있고 params(/about/:name 형식) 정보를 가짐!
URL 쿼리의 경우엔 컴포넌트 내에서 동적으로 사용할 수 있고, params의 경우엔 사용하기 전에
라우트에서 지정해주어야 한다.
params
먼저 params부터 사용을 해보자!!
위 App 컴포넌트에 /About/:name 라우트를 추가해보자!
import React from 'react';
import {Route} from 'react-router-dom';
import { Home, About } from 'pages';
const App = () => {
return (
<div>
<Route exact path = "/" component = {Home} />
<Route path = "/about" component = {About} />
<Route path = "/about/:name" component = {About} />
</div>
);
}
URL에 params를 설정할 때에는 : 형식을 사용한다.
이렇게 사용하면,
import React from 'react';
const About = ({match}) => {
return (
<div>
<h2>About {match.params.name}</h2>
</div>
);
};
export default About;
About 컴포넌트에서 match.params. 파라미터명을 통해 확일할 수 있다.
근데?!
<Route path = "/about" component = {About} />
<Route path = "/about/:name" component = {About} />
exact 없이 이렇게 사용하면 중복된다고 했을 텐데?!
그렇다... 진짜 중복이 되어 그냥 About 1개와 name 파라미터가 포함된 About이 렌더링 된다.
이를 해결하는 방법은??
exact를 사용하면 된다. 혹은 Switch컴포넌트를 사용하는 방법도 있다!
import React from 'react';
import {Route,Switch} from 'react-router-dom';
import { Home, About } from 'pages';
const App = () => {
return (
<div>
<Route exact path = "/" component = {Home} />
<Switch>
<Route path = "/about" component = {About} />
<Route path = "/about/:name" component = {About} />
</Switch>
</div>
);
}
라우트들을 Switch컴포넌트로 감싸면 매칭 되는 첫 번째 라우트만 보여주고
나머지는 보여주지 않는다!
주의할 점은 먼저 비교할 라우트를 위에 작성해야 한다는 점이다!
만약 /about이 /about/:name보다 위에 있다면, /about이 먼저 나타난다!
URL 쿼리
리액트 라우터에서 URL 쿼리를 해석하는 방법이 몇 가지 있다.
라이브러리를 사용하는 방법이 있다.
yarn add query-string
import React from 'react';
import queryString from 'query-string';
const About = ({location, match}) => {
const query = queryString.parse(location.search);
console.log(query);
return (
<div>
<h2>About {match.params.name}</h2>
</div>
);
};
export default About;
About.js에서 location을 받아서 search를 통해 가져온 쿼리를 queryString으로 파싱 해주었다.
/about/foo? detail=true 경로로 들어갔을 때
console.log(query); 를 확인하면 {detail : "true"}가 나온다.
여기서 쿼리문에서 주의할 점은 받아오는 모든 값은 문자열이라는 것이다. 그래서 비교를 해야 할 때
알맞은 형태로 변환을 시킨 다음에 비교를 해야 한다.
그래서 어떻게 이동하는 데???
웹 내에서 다른 라우트로 이동할 때에는, 일반 <a href... > foo </a> 형식으로 하면 안 된다.
왜냐하면 a 태그는 새로고침을 하기 때문이다.
새로고침을 막으면서, 리액트 라우터에 있는 페이지로 화면 전환을 하기 위해선
Link 컴포넌트를 사용하면 된다.
Link 컴포넌트
import React from 'react';
import { Link } from 'react-router-dom';
const Menu = () => {
return (
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/about/foo">About Foo</Link></li>
</ul>
<hr/>
</div>
);
};
export default Menu;
사용하는 방법은 매우 단순하다!
Link 컴포넌트를 가져와서 사용하고 to 속성을 통해 경로를 말해주면 된다.
이 컴포넌트에 전달되는 props 들은 컴포넌트 내부의 DOM 에도 전달이 되므로,
일반 DOM 엘리먼트에 설정하는 것처럼 className, style 혹은 onClick 등의 이벤트를 전달 가능!
NavLink 컴포넌트
NavLink 컴포넌트는 Link와 비슷한데, 설정한 URL이 활성화가 되면, 특정 스타일 혹은 클래스 지정이 된다.
import React from 'react';
import { NavLink } from 'react-router-dom';
const Menu = () => {
const activeStyle = {
color: 'green',
fontSize: '2rem'
};
return (
<div>
<ul>
<li><NavLink exact to="/" activeStyle={activeStyle}>Home</NavLink></li>
<li><NavLink exact to="/about" activeStyle={activeStyle}>About</NavLink></li>
<li><NavLink to="/about/foo" activeStyle={activeStyle}>About Foo</NavLink></li>
</ul>
<hr/>
</div>
);
};
export default Menu;
Route를 지정할 때처럼, 중첩될 수 있는 라우트들은 exact로 설정해야 한다.
그리고 활성화되었을 때 특정 클래스를 설정하고 싶다면 activeClassName을 설정해 줄 수 있다.
activeStyle은 보는 바와 같이 스타일을 설정할 수 있다.
라우트 속에서 또 라우트는 어떻게 설정하냐??
react-router를 사용할 때 Route 내부에서 Route를 설정하는 일이 필요하다...
First 컴포넌트에서 Second 컴포넌트로 들어가는 형식이 있을 수 있다.
import React from 'react';
import { Link, Route } from 'react-router-dom';
import { Post } from 'pages';
const Posts = ({match}) => {
return (
<div>
<h2>Post List</h2>
<ul>
<li><Link to={`${match.url}/1`}>Post #1</Link></li>
<li><Link to={`${match.url}/2`}>Post #2</Link></li>
<li><Link to={`${match.url}/3`}>Post #3</Link></li>
<li><Link to={`${match.url}/4`}>Post #4</Link></li>
</ul>
<Route exact path={match.url} render={()=>(<h3>Please select any post</h3>)}/>
<Route path={`${match.url}/:id`} component={Post}/>
</div>
);
};
export default Posts;
/post/1 ,/post/2 ,/post/3 ,/post/4 같은 경우 모두 post를 통해 들어간다.
Link를 설정하는 부분에 match.url을 사용하는 데, 이 url은 현재 라우트의 경로를 나타낸다.
<Route exact path={match.url} render={()=>(<h3>Please select any post</h3>)}/>
<Route path={${match.url}/:id} component={Post}/>
Route를 설정할 때 첫 번째 라우트는 match.url로 설정되었기 때문에 post의 id가 주어지지 않을 땔
의미한다. 그리고 여기서 component 대신 render를 사용한다.
이 render는 해당 태그만 렌더링 시켜준다.
두 번째 라우트에선 라우트의 주소에 :id가 붙을 경우 Post 컴포넌트를 보여주도록 설정했다.
이렇게 중첩된 라우트를 설정할 수 있다.
더 많다면 Route를 더 추가해주면?? 끝!
헷갈리는 값들...
라우트가 받는 props 중에서, 헷갈리는 값들이 꽤 많다!
/post/1 주소를 기준으로
- location.pathname : /post/1
- match.path : /post/:id
- match.url : /post/1
이것의 결과물은 모두 비슷한 것 같다.. 어떻게 구분하지??
location.pathname 은 현재 브라우저 상의 위치다. 이 값은 어떤 라우트에서 렌더링 하든 동일하다.
match 관련은 설정한 Route와 직접적으로 관계된 값만 보여준다.
만약 /post에서 나타낸다면 path와 url 모두 /post 일 것이다.
하지만 /post/1 에선 path는 라우트에서 설정한 path가 그대로, url은 값이 들어간 상태로 나타낸다.
'React > 기능' 카테고리의 다른 글
[React] useLayoutEffect (0) | 2022.02.08 |
---|---|
[React] useRef (0) | 2022.02.08 |
[React] useEffect (0) | 2022.02.08 |
[React] useState (0) | 2022.02.08 |
[React] Route 부가적인 부분 (history, withRouter..) (0) | 2022.02.08 |