npm i react-router
npm i react-router-dom
npm i react-router-native
import { BrowserRouter , Route} from 'react-router-dom'
React.DOM.render(<BrowserRouter> <Hot / > </BrowserRouter>, docu~~)
return (
<BrowserRouter>
<div>
<Link to="경로1">숫자야구</Link> //Link는 router안에 있어야 동작
<Link to="경로2">게임</Link>
</div>
////위에는 공통으로 화면이 바뀌지 않는 부분
//// 아래는 화면이 바뀌는 부분
<div>
<Route path = "경로1" component={NumberBaseBall}/ >
<Route path = "경로2" component={Game}/ >
</div>
</BrowserRouter>
)
새로고침, 주소창에 직접 주소를 입력하면 서버쪽에 요청하는 것이기때문에 에러가난다.
서버는 이 주소를 모르고 client인 react만 알고 있는 주소다
return (
<BrowserRouter>
<div>
<Link to="/game/index">게임</Link>
<Link to="/game/baseball">숫자야구</Link>
</div>
<div>
<Route path = "/game/:name" component={GameMatcher}/ > // 여기서 router가 props를 넣어주는 것
</div>
</BrowserRouter>
path는 두 단어로 이루어져있어야 한다.
props로 연결 안되어있는데 history, match, location을 쓰고 싶을 때 -> withRouter사용
라우터로 연결하지 않은 컴포넌트에서 history, match, location을 쓰고 싶을 때 withRouter를 사용한다
주로 로그인 했을 때 로그인이 성공하면 페이지를 이동 할 때 사용한다.
아래처럼 컴포넌트를 withRouter로 감싸주면 된다.
export default withRouter(WithRouterSample);
match값은 컴포넌트가 불러진 곳의 값을 나타내지만 location은 현재 페이지의 값을 나타낸다
WithRouterSample.js
function WithRouterSample({ history, location, match }) {
return (
<>
<textarea
readOnly
value={JSON.stringify(location, null, 2)}
/>
<textarea
readOnly
value={JSON.stringify(match, null, 2)}
/>
<button onClick={() => history.push("/")}>홈으로 이동</button>
</>
);
}
export default withRouter(WithRouterSample);
참고로 JSON.stringify(location, null, 2)의 null과 2의 의미는 들여쓰기를 한다는 뜻이다.
profiles.js
function Profiles() {
return (
<>
<ul>
<li>
<Link to="/profiles/user">user</Link>
</li>
<li>
<Link to="/profiles/gildong">gildong</Link>
</li>
</ul>
<Route
path="/profiles"
exact
render={() => <div>사용자를 선택해주세요</div>}
/>
<Route path="/profiles/:username" component={Profile} />
<WithRouterSample />
</>
);
}
export default Profiles;
Link를 클릭해서 서브라우트를 통해 이동한다 하더라도 profiles컴포넌트의 match값을 나타내는 반면 location은 Link를 클릭해서 이동한 profile의 location값을 나타낸다.
withRouter대신 hook를 사용할 수 있다.
yarn add use-react-router
우선 위와 같이 hook을 설치한 뒤 아래처럼 사용하면 된다.
import useReactRouter from 'use-react-router';
function RouterHookSample() {
const { history, location, match } = useReactRouter;
console.log({ history, location, match });
return null;
}
export default RouterHookSample;
페이지를 이탈할 때 경고창을 띄운다. 주로 작성중인 페이지가 있는데 페이지를 이동하려 할 때 사용한다.
useEffect(() => {
const unBlock = history.block("정말 떠나실 건가요?");
return () => {
unBlock();
};
}, [history]);
return으로 컴포넌트가 unMount될 때 history block을 제거해야지 하지 않으면 다른 페이지에서도 계속 block이 발생한다.
if(this.props.match.params.name === 'baseball') {
return <Baseball />
}
페이지 주소에 유동적인 값을 전달할 경우 파라미터와 쿼리로 나눠질수 있다.
파라미터: /profiles/velopert (정해진 특정 데이터를 조회할 때)
쿼리: /about?details=true (다양한 옵션을 줘서 조회할 때)
match로 조회
props로 match값을 받아와서 사용 : match.params로 조회
<Route path='/about/:username component={User}'>
username부분이 match의 값이 된다.
loaction으로 조회
props로 loaction값을 받아와서 사용 : loaction.search로 조회
이 query를 추출하기 위해 qs라이브러리를 사용한다
query 파싱 라이브러리
yarn add qs
우선 설치 후
const query = qs.parse(location.search, {
ignoreQueryPrefix: true
})
ignoreQueryPrefix를 true로 설정해야 ?를 제외 후 파싱한다.
false로 설정한다면 아래처럼 ?를 포함해서 파싱한다.
{?data:'1'}
참고로 파싱된 모든 값은 문자열로 저장이 된다.
switch 사용법은 Route를 switch로 감싸주면 된다.
switch는 위에서부터 읽기 시작하여 해당하는 path를 발견하면 멈춘다. 때문에 아래와 같은 예제에서 /game을 입력해도 /도 해당되기 때문에 NumberBaseBall을 렌더링하는 문제가 발생한다.
<Switch>
<Route path = "/" component={NumberBaseBall}/ >
<Route path = "/game" component={Game}/ >
</Switch>
위와 같이 path의 / 부분이 곂치기 때문에 react는 두개가 모두 해당한다고 판단하여 두 component 모두 렌더링을 한다.
막기위해서는 exact를 사용
<Switch>
<Route path = "/" exact component={NumberBaseBall}/ >
<Route path = "/game" component={Game}/ >
</Switch>
switch는 존재하지 않는 경로일때 경고 메세지를 띄우기 위해 사용할 수 있다.
<Switch>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} />
<Route
render={({ location }) => (
<div>
<h2>이 페이지는 존재하지 않습니다. :</h2>
<p>{location.pathname}</p>
</div>
)}
/>
</Switch>
참고
: render는 컴포넌트로 연결하지 않고 렌더링할 페이지를 바로 함수로 만들 수 있다.위와 같이 하단에 Route 컴포넌트에 location이 없으면 에러 메세지를 띄워준다.
NavLink 는 Link 랑 비슷한데, 현재 경로와 Link 에서 사용하는 경로가 일치하는 경우 특정 스타일 혹은 클래스를 적용 할 수 있다.
<NavLink
to="/profiles/user"
activeStyle={{ background: "black", color: "white" }}
activeClassName="active"
>
user
</NavLink>
<NavLink
to="/profiles/user"
activeStyle={{ background: "black", color: "white" }}
isActive={(match, location) => {
return match.params.blbal = 'abkd' //참이면 activeStyle 적용
}}
>
user
</NavLink>
history.block을 컴포넌트 형태로 사용
<Prompt when={formIsHalfFilledOut} message='떠나실건가요?'/>
컴포넌트를 특정 페이지로 이동
history.push를 컴포넌트 형태로 사용
<Redirect to="/about" />
JSX 형태로 라우트를 선언하는 것이 아닌 Angular 나 Vue 처럼 배열/객체를 사용하여 라우트 정의하기