April 30, 2020
리액트에서 SPA 싱글페이지라고 해서 화면이 한 종류는 아니다. 서버에서 사용자에게 제공하는 페이지는 한 종류이지만, 해당 페이지에서 로딩된 자바스크립트와 현재 사용자 브라우저의 주소 상태에 따라 다양한 화면을 보여준다. 다른 주소에 다른 화면을 보여주는것을 라우팅이라고 한다. 리액트 자체에 이 기능이 내장되어 있지않아서 라이브러리를 사용하여 이 작업을 하는데, 리액트 라우터, 리치 라우터, Next.js등 여러가지가 있다. 리액트 라우터를 주로 사용
npm install react-router-dom
index.js 파일에서 react-router-dom에 내장되어있는 BrowserRouter라는 컴포넌트를 사용하여 감싼다. 이 컴포넌트는 웹 어플리케이션에 HTML5의 History API를 사용하여 새로고침하지 않고 주소를 변경하고 주소에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 해준다.
import { BrowserRouter } from 'react-router-dom';
...
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
)
Route라는 컴포넌트를 사용하여 사용자의 경로에 따라 다른 컴포넌트를 보여준다.
<Route path="주소규칙" componen={보여줄 컴포넌트} />
Link컴포넌트는 클릭 시 다른 주소로 이동시켜주는 컴포넌트이다. 일반 웹 어플리케이션에서 a태그를 사용한다면, 리액트 라우터를 사용할 떄는 a태그를 사용하면 페이지를 새로 불러오기 떄문에 상태를 모두 날린다. link컴포넌트를 사용하면 페이지를 새로 불러오지 않고 주소만 변경해준다.
<Link to="주소">내용</Link>
path props를 배열로 설정해주면 여러 경로에서 같은 컴포넌트를 보여줄 수 있다.
<Route path={['/first', '/second']} component={cpnt} />
이렇게 설정하면 /first 와 /second에 접속했을떄 cpnt컴포넌트를 보여준다.
유동적인 값을 사용해야 하는 상황에서 파라미터를 써야할지 쿼리를 써야할지 따라야하는 규칙은 없으나, 일반적으로 파라미터는 특정 아이디 혹은 이름을 사용하여 조회할때 사용하고, 쿼리는 어떤 키워드를 검색하거나 페이지에 필요한 옵션을 전달할때 사용한다.
URL 파라미터를 사용할때는 라우트로 사용되는 컴포넌트에서 받아오는 match라는 객체 안의 params 값을 참조한다. path규칙에는 /path/:params 이라고 넣어준다.
const Profile = ({match}) => {
const {params} = match.params;
}
...
<Route path="/profile/:params" component={Profile}>
...
쿼리는 location 객체에 들어있는 search 값에서 조회가 가능하다. location객체는 라우트로 사용된 컴포넌트에 props로 전달되며, 주소에대한 정보를 지니고 있다.
location의 형태
{
"pathname": "/about",
"search": "?detail=true",
"hash": ""
}
/about?detail=true주소로 들어갔을 떄의 값. URL쿼리를 읽을때는 search값을 확인해야 하는데, 문자열 형태로 되어있다. 특정 값을 읽어오기 위해 이 문자열을 객체 형태로 변환해주어야하는데 qs라는 라이브러리를 사용하면 된다.
npm install qs
const About = ({ location }) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true, // 뮨저욜 맨 앞의 ?를 생략
})
const showDetail = query.detail === 'true' // 쿼리의 파싱 결과값은 문자열
}
history객체는 라우트로 사용된 컴포넌트에 match, location과 함꼐 전달되는 props중 하나로 이 객체를 통해 라우터 API를 호출할 수 있다.
// 뒤로가기
handleGoBack = () => {
history.goBack();
};
// 홈으로 이동
handleGoHome = () => {
history.push('/')
}
// 페이지에 변화가 생기려고 할때마다 정말 나가나 질문
componenetDidMount() {
this.unblock = history.block('정말 나가시나요?')
}
// 컴포넌트가 언마운트되면 질문을 멈춤
componenetWillUnmount() {
if(this.unblock) {
this.unblock()
}
}
withRouter함수는 HOC이다 라우트로 사용되는 컴포넌트가 아니어도 match,location, history객체를 접근할 수 있게 해준다.
import {withRouter} from 'react-router-dom'
...
const WithRouter = ({location, match, history}) => {
console.log(location, match, history)
...
}
export default withRouter(WithRouter)
이렇게 익스포트 시 감싸준다.
Switch 컴포넌트는 여러 Route를 감싸서 그중 일치하는 하나의 라우트만을 렌더링 시켜준다. 모든 규칙과 일치하지 않을때 보여줄 not found 페이지도 구현 가능하다.
import {Route, Link, Switch} from 'react-router-dom'
...
const App () => {
return (
<Switch>
<Route path="/" component={Home}>
<Route path="/first" component={First}>
<Route path="/second" component={Second}>
<Route
render={() => (
<div>
<h2>존재하지 않는 페이지</h2>
</div>
)}
>
</Switch>
)
}
path를 따로 정의하지 않으면 모든 상황에 렌더링.