예전에는 사용자에게 보이는 화면을 서버 측에서 준비했습니다. (요청할때마다 HTML 전송)
사용자와의 인터랙션이 자주 발생하는 모던 웹에서는 적당하지 않을수도 있습니다.
그래서 리액트 같은 라이브러리는 뷰 렌더링을 사용자의 브라우저가 담당하도록 합니다. (예전엔 아닌었나보네)
사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트 해줍니다.
SPA의 경우 서버에서 제공하는 페이지는 한 종류이지만, 해당 페이지에서 로딩된 자바스크립트와 현재 사용자 브라우저의 주소 상태에 따라 다양한 화면을 보여 줄 수 있습니다.
다른 주소에 다른 화면을 보여 주는 것을 라우팅이라고 합니다.
react-router-dom에 내장되어 있는 BrowserRouter라는 컴포넌트를 사용하여 감싸면 됩니다. 이 컴포넌트는 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로고침하지 않고도 주소를 변경하고, 현재 주소에 관련된 정보를 props로 쉽게 조회하거나 사용할 수 있도록 해 줍니다.
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter> // 이 부분
<App />
</BrowserRouter>,
document.getElementById("root")
);
reportWebVitals();
home 와 about 컴포넌트를 만들고 라우팅해줬습니다.
/ 는 exact 라는 props를 true 설정해야 딱 그것만 나옵니다.
import React from "react";
import { Route } from "react-router-dom";
import About from "./About";
import Home from "./Home";
const App = () => {
return (
<div>
<Route path="/" component={Home} exact={true} />
<Route path="/about" component={About} />
</div>
);
};
export default App;
일반적으로 파라미터는 특정 아이디 혹은 이름을 사용하여 조회할 때 사용하고, 쿼리는 우리가 어떤 키워드를 검색하거나 페이지에 필요한 옵션을 전달할 때 사용합니다.
<Route path="/profile/:username" component={Profile} />
이런식으로 사용하면
import React from "react";
const data = {
velopert: {
name: "김민준",
description: "리액트를 좋아하는 개발자",
},
gildong: {
name: "홍길동",
description: "고전 소설 홍길동전의 주인공",
},
};
const Profile = ({ match }) => {
console.log("match 가 들어오는지 확인", match);
const { username } = match.params;
const profile = data[username];
if (!profile) {
return <div>존재하지 않는 사용자압니다.</div>;
}
return (
<div>
<h3>
{username}({profile.name})
</h3>
<p>{profile.description}</p>
</div>
);
};
export default Profile;
이런식으로 사용합니다. match 객체는 아래와 같은 구조를 가집니다.
{
isExact: true
params: {username: "velopert"}
path: "/profile/:username"
url: "/profile/velopert"
}
yarn add qs 하고
import React from "react";
import qs from "qs";
const About = ({ location }) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true,
});
const showDetail = query.detail === "true";
return (
<div>
<h1>소개</h1>
<p>
.이 프로젝트는 리액트 라우터 기초를 실습해 보는 예제 프로젝트입니다.
</p>
{showDetail && <p> detail 값을 true로 설정하셧군요!</p>}
</div>
);
};
export default About;
통해서 쿼리스트링을 객체로 해서 값을 렌더했습니다.
브라우저에서 http://localhost:3000/about?detail=true 를 입력하면 됩니다.
그냥 라우트로 사용되고 있는 컴포넌트의 내부에 Route 컴포넌트를 또 사용하면 됩니다.
Profiles.js
import React from "react";
import { Link, Route } from "react-router-dom";
import Profile from "./Profile";
const Profiles = () => {
return (
<div>
<h3>사용자 목록:</h3>
<ul>
<li>
<Link to="/profiles/velopert">velopert</Link>
</li>
<li>
<Link to="/profiles/gildong">gildong</Link>
</li>
</ul>
<Route
path="/profiles"
exact
render={() => <div>사용자를 선택해 주세요</div>}
/>
<Route path="/profiles/:username" component={Profile} />
</div>
);
};
export default Profiles;
App.js
import React from "react";
import { Route, Link } from "react-router-dom";
import About from "./About";
import Home from "./Home";
import Profiles from "./Profiles";
const App = () => {
return (
<div>
<ul>
<li>
<Link to="/">홈</Link>
</li>
<li>
<Link to="/about">소개</Link>
</li>
<li>
<Link to="/profiles"> 프로필</Link>
</li>
</ul>
<Route path="/" component={Home} exact={true} />
<Route path={["/about", "/info"]} component={About} />
<Route path="/profiles" component={Profiles} />
</div>
);
};
export default App;
(감기몸살 걸림ㅜ)
history 객체는 라우트로 사용된 컴포넌트에 match, location 과 함께 전달되는 기본 props 중 하나 입니다.
특정 버튼을 눌렀을 때 뒤로 가거나, 로그인 후 화면을 전환하거나, 다른 페이지로 이탈하는 것을 방지해야 할 때 history를 활용합니다.
import React, { Component } from "react";
class HistorySample extends Component {
// 뒤로 가기
handleGoBack = () => {
this.props.history.goBack();
};
handleGoHome = () => {
this.props.history.push("/");
};
componentDidMount() {
// 이것을 설정하고 나면 페이지에 변화가 생기려고 하 때마다 정말 나갈 것인지를 질문함
this.unblock = this.props.history.block("정말 떠나실 건까요?");
}
componentWillUnmount() {
// 컴포넌트가 언마운트 되면 질문을 멈춤
if (this.unblock) {
this.unblock();
}
}
render() {
return (
<div>
<button onClick={this.handleGoBack}>뒤로</button>
<button onClick={this.handleGoHome}>홈으로</button>
</div>
);
}
}
export default HistorySample;
withRouter 함수는 라우트로 사용된 컴포넌트가 아니어도 match, location, history 객체에 접근하능합니다.
Switch를 사용하면 모든 규칙과 일치하지 않을 때 보여줄 Not Found 페이지도 구현할수 있습니다.
import React from "react";
import { NavLink, Route } from "react-router-dom";
import Profile from "./Profile";
import WithRouterSample from "./WithRouterSample";
const Profiles = () => {
const activeStyle = {
background: "black",
color: "white",
};
return (
<div>
<h3>사용자 목록:</h3>
<ul>
<li>
<NavLink activeStyle={activeStyle} to="/profiles/velopert" setAc>
velopert
</NavLink>
</li>
<li>
<NavLink activeStyle={activeStyle} to="/profiles/gildong">
gildong
</NavLink>
</li>
</ul>
<Route
path="/profiles"
exact
render={() => <div>사용자를 선택해 주세요</div>}
/>
<Route path="/profiles/:username" component={Profile} />
<WithRouterSample />
</div>
);
};
export default Profiles;
링크말고 NavLink를 써야겠다.
링크가 활성화 되었을때 스타일을 적용할수 있습니다.