react-router๋ฅผ ํตํ ๋ฆฌ์กํธ ์ฑ๊ธ ํ์ด์ง ์ดํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ
1. ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ
$ yarn add react-router-dom
ํ๋ก์ ํธ์ ๋ผ์ฐํฐ ์ ์ฉ
<src/index.js>
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'; // * BrowserRouter ๋ถ๋ฌ์ค๊ธฐ
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// * App ์ BrowserRouter ๋ก ๊ฐ์ธ๊ธฐ
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
serviceWorker.unregister();
Route: ํน์ ์ฃผ์์ ์ปดํฌ๋ํธ ์ฐ๊ฒฐํ๊ธฐ
Link: ๋๋ฅด๋ฉด ๋ค๋ฅธ ์ฃผ์๋ก ์ด๋์ํค๊ธฐ
import { Route, Link } from 'react-router-dom';
<Route path="์ฃผ์๊ท์น" component={๋ณด์ฌ์ฃผ๊ณ ์ถ์ ์ปดํฌ๋ํธ}>
<src/App.js>
import React from 'react';
import { Route, Link } from 'react-router-dom';
import About from './About';
import Home from './Home';
const App = () => {
return (
<div>
<ul>
<li>
<Link to="/">ํ</Link>
</li>
<li>
<Link to="/about">์๊ฐ</Link>
</li>
</ul>
<hr />
<Route path="/" exact={true} component={Home} />
<Route path="/about" component={About} />
<Route
path="/profiles"
exact
render={() => <div>์ ์ ๋ฅผ ์ ํํด์ฃผ์ธ์.</div>}
/> // render: ์ปดํฌ๋ํธ๊ฐ ์๋๋ผ JSX ์์ฒด๋ฅผ ๋ ๋๋งํ ์ ์๋ค.
</div>
);
};
export default App;
exact: ํด๋น ๊ฒฝ๋ก๋ง ์ฐ๊ฒฐ (/ O /about X)
2. ํ๋ผ๋ฏธํฐ์ ์ฟผ๋ฆฌ => ํ์ด์ง ์ฃผ์ ์ ์
- ํ๋ผ๋ฏธํฐ: /profiles/velopert
- ์ฟผ๋ฆฌ: /about?details=true
์ผ๋ฐ์ ์ผ๋ก ํ๋ผ๋ฏธํฐ๋ ํน์ id๋ ์ด๋ฆ์ ๊ฐ์ง๊ณ ์กฐํํ ๋,
์ฟผ๋ฆฌ๋ ์ด๋ค ํค์๋๋ฅผ ๊ฒ์ํ๊ฑฐ๋, ์์ฒญ์ ํ ๋ ํ์ํ ์ต์ ์ ์ ๋ฌํ ๋ ์ฌ์ฉ
ํ๋ผ๋ฏธํฐ
ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ์์ฌ ๋ match ์์ ๋ค์ด์๋ params ๊ฐ์ ์ฐธ์กฐํ๋ค.
match ๊ฐ์ฒด ์์๋ ํ์ฌ์ ์ฃผ์๊ฐ Route ์ปดํฌ๋ํธ์์ ์ ํ ๊ท์น๊ณผ ์ด๋ป๊ฒ ์ผ์นํ๋์ง์ ๋ํ ์ ๋ณด๊ฐ ๋ค์ด์๋ค.
<src/Profile.js>
const { username } = match.params;
<src.App.js>
<Route path="/profiles/:username" component={Profile} />
์ฟผ๋ฆฌ
์ฟผ๋ฆฌ๋ ๋ผ์ฐํธ ์ปดํฌ๋ํธ์๊ฒ props ์ ๋ฌ๋๋ location ๊ฐ์ฒด์ ์๋ search ๊ฐ์์ ์ฝ์ด์ฌ ์ ์๋ค.
location ๊ฐ์ฒด๋ ํ์ฌ ์ฑ์ด ๊ฐ๊ณ ์๋ ์ฃผ์์ ๋ํ ์ ๋ณด๋ฅผ ์ง๋๊ณ ์๋ค.
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere'
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
search๊ฐ ๋ฌธ์์ด ํํ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด ํํ๋ก ๋ณํํด์ฃผ์ด์ผ ํ๋ค. => qs ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
$ yarn add qs
<src/About.js>
const query = qs.parse(location.search, {
ignoreQueryPrefix: true
});
const detail = query.detail === 'true'; // ์ฟผ๋ฆฌ์ ํ์ฑ๊ฒฐ๊ณผ๊ฐ์ ๋ฌธ์์ด์
๋๋ค.
3. ์๋ธ๋ผ์ฐํธ (๋ผ์ฐํธ ๋ด๋ถ์ ๋ผ์ฐํธ)
4. ๋ฆฌ์กํธ ๋ผ์ฐํฐ ๋ถ๊ฐ๊ธฐ๋ฅ
history ๊ฐ์ฒด
์ฐ๋ฆฌ๊ฐ ์ปดํฌ๋ํธ ๋ด์ ๊ตฌํํ๋ ๋ฉ์๋์์ ๋ผ์ฐํฐ์ ์ง์ ์ ๊ทผํ ์ ์๋ค. (ex ๋ค๋ก๊ฐ๊ธฐ, ํน์ ๊ฒฝ๋ก๋ก ์ด๋, ์ดํ ๋ฐฉ์ง ๋ฑ)
<HistorySample.js>
import React, { useEffect } from 'react';
function HistorySample({ history }) {
const goBack = () => {
history.goBack();
};
const goHome = () => {
history.push('/');
};
useEffect(() => {
console.log(history);
const unblock = history.block('์ ๋ง ๋ ๋์ค๊ฑด๊ฐ์?');
return () => {
unblock();
};
}, [history]);
return (
<div>
<button onClick={goBack}>๋ค๋ก๊ฐ๊ธฐ</button>
<button onClick={goHome}>ํ์ผ๋ก</button>
</div>
);
}
export default HistorySample;
withRouter HoC
๋ผ์ฐํธ ์ปดํฌ๋ํธ๊ฐ ์๋ ๊ณณ์์ match / location / history๋ฅผ ์ฌ์ฉํด์ผ ํ ๋ ์ฌ์ฉ
import { withRouter } from 'react-router-dom';
<WithRouterSample.js>
import React from 'react';
import { withRouter } from 'react-router-dom';
const WithRouterSample = ({ location, match, history }) => {
return (
<div>
<h4>location</h4>
<textarea value={JSON.stringify(location, null, 2)} readOnly />
<h4>match</h4>
<textarea value={JSON.stringify(match, null, 2)} readOnly />
<button onClick={() => history.push('/')}>ํ์ผ๋ก</button>
</div>
);
};
export default withRouter(WithRouterSample);
Switch
์ฌ๋ฌ Route๋ค์ ๊ฐ์ธ์ ๊ทธ ์ค ๊ท์น์ด ์ผ์นํ๋ ๋ผ์ฐํธ ๋จ ํ๋๋ง์ ๋ ๋๋ง
=> ์๋ฌด๊ฒ๋ ์ผ์นํ์ง ์์์ ๋ ๋ณด์ฌ์ค Not Found ํ์ด์ง ๊ตฌํ ๊ฐ๋ฅ!
import { Switch } from 'react-router-dom';
<App.js>
<Switch>
<Route path="/" exact={true} component={Home} />
<Route path="/about" component={About} />
<Route path="/profiles" component={Profiles} />
<Route path="/history" component={HistorySample} />
<Route
// path ๋ฅผ ๋ฐ๋ก ์ ์ํ์ง ์์ผ๋ฉด ๋ชจ๋ ์ํฉ์ ๋ ๋๋ง๋จ
render={({ location }) => (
<div>
<h2>์ด ํ์ด์ง๋ ์กด์ฌํ์ง ์์ต๋๋ค:</h2>
<p>{location.pathname}</p>
</div>
)}
/>
</Switch>
NavLink
ํ์ฌ ๊ฒฝ๋ก์ Link์์ ์ฌ์ฉํ๋ ๊ฒฝ๋ก๊ฐ ์ผ์นํ๋ ๊ฒฝ์ฐ ํน์ ์คํ์ผ ํน์ ํด๋์ค๋ฅผ ์ ์ฉ
import { NavLink } from 'react-router-dom';
<App.js>
<NavLink
to="/profiles/velopert"
activeStyle={{ background: 'black', color: 'white' }}
>
๊ธฐํ
- Redirect: ํ์ด์ง๋ฅผ ๋ฆฌ๋๋ ํธ ํ๋ ์ปดํฌ๋ํธ
- Prompt: ์ด์ ์ ์ฌ์ฉํ๋ history.block ์ ์ปดํฌ๋ํธ ๋ฒ์
- Route Config: JSX ํํ๋ก ๋ผ์ฐํธ๋ฅผ ์ ์ธํ๋ ๊ฒ์ด ์๋ Angular ๋ Vue ์ฒ๋ผ ๋ฐฐ์ด/๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํธ ์ ์ํ๊ธฐ
- Memory Router ์ค์ ๋ก ์ฃผ์๋ ์กด์ฌํ์ง๋ ์๋ ๋ผ์ฐํฐ. ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ๋, ์๋ฒ ๋๋ ์น์ฑ์์ ์ฌ์ฉํ๋ฉด ์ ์ฉํ๋ค.
5. useReactRouter Hook ์ฌ์ฉํ๊ธฐ
=> ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ ๋ผ์ฐํฐ์ ๊ด๋ จ๋ ๊ฐ(match, history, location ๋ฑ)๋ค์ Hook์ผ๋ก ์ฌ์ฉํ๊ธฐ (๊ณต์ X)
=> withRouter๋ ๋ชฉ์ ์ ๋น์ท
$ yarn add use-react-router
import useReactRouter from 'use-react-router';
<RouterHookSample.js>
import useReactRouter from 'use-react-router';
function RouterHookSample() {
const { history, location, match } = useReactRouter;
console.log({ history, location, match });
return null;
}
export default RouterHookSample;
'โ๏ธ > React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React ๊ณต๋ถํ๊ธฐ(7) - ๋ฆฌ๋์ค ๋ฏธ๋ค์จ์ด (0) | 2021.11.09 |
---|---|
React ๊ณต๋ถํ๊ธฐ(6) - ๋ฆฌ๋์ค(Redux) (0) | 2021.11.05 |
React ๊ณต๋ถํ๊ธฐ(4) - API ์ฐ๋ํ๊ธฐ (0) | 2021.11.05 |
React ๊ณต๋ถํ๊ธฐ(2) - styled-components (0) | 2021.10.15 |
React ๊ณต๋ถํ๊ธฐ(1) - Hooks ์ข ๋ฅํธ (0) | 2021.10.10 |