elice/토끼성장일지

[엘리스 AI트랙] 리액트 라우터(React-Router)

Juliie 2021. 10. 20. 15:46

Declarative Routing for React

 

리액트 라우터 공식 문서

공식 문서에서는 React Router를 Declarative Routing for React로 정의하고 있다

이게 머야,,,싶어서 검색한 끝에 잘 설명해주는 글 발견 (🙋‍♀️ 멋진 코드 예제들이 있어요!)

 

https://stackoverflow.com/questions/33655534/difference-between-declarative-and-imperative-in-react-js

 

Difference between declarative and imperative in React.js?

Recently I've been studying a lot about the functionality and the ways to use the Facebook JavaScript library React.js. When speaking of its differences to the rest of the JavaScript world often th...

stackoverflow.com

https://codeburst.io/declarative-vs-imperative-programming-a8a7c93d9ad2

 

Declarative vs Imperative Programming

Or wrong ways I was thinking about React

codeburst.io

https://egas.tistory.com/2

 

선언형 프로그래밍과 명령형 프로그래밍

React의 특징 중 하나에 선언형이 있다. 선언형은 무엇을 의미할까? 프로그래밍 패러다임은 프로그램을 작성할 때의 관점을 의미한다. 우리가 아는 객체지향도 프로그래밍 패러다임 중 일부이다.

egas.tistory.com

 

이런 느낌일까...?

// 1. 명령형 언어
if (손님 === '토끼') {
	집 청소하기()
    복숭아 사기()
    토끼 사료 사기()
    건초 사기()
    담요 깔아드리기()
} else if (손님 === '고양이') {
	말린 닭고기 사기()
}

// 2. 선언형 언어
if (손님 === '토끼') {
	return <토끼손님 />
} else if (손님 === '고양이') {
	return <고양이 />
}

생각해보니까 리액트는 선언형 언어라고 했는데! 까먹고 있었다

이제 선언형 뷰의 장점들이 이해가 약간 갔다🤔

react-router의 기능

 

  • 리액트 컴포넌트를 특정 path와 연결하면, 해당하는 path로 진입시 컴포넌트를 렌더링하게 함
<Route path="/yeolmoo">
	<YoungRadish />
</Route>
  • URL 파라미터(ex: query, path variable 등)를 얻어 활용 가능

  • 조건에 맞지 않을 경우 redirect 함
  • 페이지 이동 시, 이벤트 핸들러를 등록할 수 있음
    • ex) history.listen()
  • /post/123 과 같은 nested route를 구현함
    • /post ➡️ 1번 포스트(/1) , 2번 포스트(/2), 3번 포스트(/3) ...
    • Route안에 Route가 들어가는 경우

 

react-router의 사용법

 

  • <BrowserRouter> 로 감싸 Router Context를 제공해야 함
  • Route로 path를 정의하고, 그 안에 렌더링하고자 하는 컴포넌트를 넣음
  • Link로 특정 페이지로 이동시, 리로드 없이 페이지가 이동함 (기본 기능)
  • Switch로 매칭되는 라우트 하나를 렌더링하게 함
    • 자식들 중 처음으로 조건이 만족하는 하나의 컴포넌트만 출력하도록 함
<BrowserRouter>
	<Switch>
    	<Route path="about" />
        	<AboutPage />
        </Route>
        <Route path="contact" />
        	<ContactPage />
        </Route>
        <Route path="/" />
        	<HomePage />
        </Route>  
    </Switch>
</BrowserRouter>

 

react-router 컴포넌트

 

1. BrowserRouter

  • HTML5의 History API를 사용하여 UI와 URL의 싱크를 맞추는 역할
    • ex) About 페이지로 들어가면 주소창에도 peach.com/ ➡️ peach.com/about 과 같은 식으로 주소가 변경된다
    • 서버에서 페이지를 새로 받아온건 아니지만...이런 처리가 있어야 URL path가 변경되는 이벤트를 브라우저가 감지할 수 있음 ➡️ 이벤트 핸들러 처리가 가능해짐
  • 모든 URL에 대해 일관성 있게 동작하게 하기 위해서는 동일한 클라이언트를 내려줄 수 있도록 서버 설정 필요
  • 모든 path 앞의 basename을 지정할 수 있음
    • ex) "peach.com/ko/users" , "peach.com/en/users", "peach.com/jp/users"...
  • forceRefresh로 페이지 이동 시 리프레시 할 것인지 지정할 수 있음

2. Swtich

  • 여러 Route 중 가장 먼저 매치되는 Route를 선택하여 렌더링함
  • 매칭 되는 Route가 없으면 아무것도 보여주지 않음
    • fallback 용으로 404 not Found 페이지를 추가함
  • path="/" 의 경우 모든 path에 매칭
    • 1) 가장 아래로 내림
    • 2) exact 키워드 추가 

3. Route

  • path와 컴포넌트를 매칭
  • 매칭되는 컴포넌트는 ❗️
    • 1) children으로 넣어주거나
    • 2) component prop으로 넘김
  • exact 키워드로 정확하게 매칭하는 path 설정 가능
// 1번 + exact 키워드
<Route exact path="/watermelon">
	<Watermelon />
</Route>

// 2번
<Route component={Watermelon} path="/watermelon" />
  • Route로 렌더링 되는 최상위 컴포넌트는 match, location, history를 prop으로 받을 수 있음
  • render prop으로 매칭되었을 때 실제 어떤 컴포넌트를 렌더링할지 통제함

뭐야,,, 그럼 render나 component prop이나 같은거 아닌가? 라는 생각이 들었는데 코치님(feat. 공식문서)이 이해 쏙쏙 가게 설명 잘 해주셨다...❤️ 사...사랑합니다 코치님 최고 ( ⁎ᵕᴗᵕ⁎ ) 

 

우선 특정 path와 매치될 때 <Route>로 컴포넌트를 렌더링 할 수 있는 방법은 아래와 같습니다.

1. 자식 element로 넣는다(공식 문서에서 추천)
<Route exact path="/">
  <Home />
</Route>

1번 방법을 사용하지 않고 다른 rendering methods를 사용할 수도 있는데(component, render, children function), 이 경우는 hook이 소개되기 전에 이전 버전의 router로 만들어진 앱을 지원하기 위해서입니다.

2. <Route component> 사용
<Router>
  <Route path="/user/:username" component={User} />
</Router>

<Route> 의 component를 사용하면 router는 주어진 컴포넌트에서 새로운 엘리먼트를 만들기 위해 React.createElement 를 사용한다고 해요. 그래서 만약에 component={() => <User />} 와 같은 형태로 만들면, 렌더링이 될 때마다 새로운 컴포넌트를 만들게 됩니다. 근데 이건 원래 있던 <User /> 컴포넌트 마운팅이 해제되지 않은 상태에서 계속 새로운 컴포넌트가 마운팅 되는 거예요! 그러니까 만약 component에 인라인 함수를 쓸 일이 있다면(예: prop으로 뭔가 넘겨준다거나...) redner를 사용하는 게 좋아요.

3. <Route render> 사용
<Router>
  <Route path="/home" render={() => <div>Home</div>} />
</Router>

사실 2번 설명까지만 읽으셔도 '아 인라인 함수로 뭔가 prop을 넘겨주거나 할 때면 route의 component를 쓸 게 아니라 render를 쓰는 거구나! 근데, component나 render를 사용하기보다는 <Route path="/user/:username"><User /></Route> 처럼 자식 컴포넌트로 넣어주는 게 더 좋은 거구나!' 라는 걸 아실 수 있어요. 이까지만 아셔도 솔직히 무리 없습니다! 그래도 render에 대해서 조금 설명해보자면 render를 사용할 땐 component와 다르게, 우리가 원하지 않는 마운팅이 되지 않게 인라인 함수를 쓸 수 있어요. 그리고 하나 주의하실 점은 <Route component>가 <Route render>보다 더 중요하기 때문에 component와 render를 같은 <Route>에 쓰지 않아야 한다는 점이에요. 아래와 같이요!
<Route component={} render={} />​

4. <Route children> function 사용 (설명 X. 필요하시면 찾아보기!)

 

공식문서쓰

4. Redirect

  • Link와 비슷하지만 렌더링 되면 to prop으로 지정한 path로 이동함
//선언적 코드
if (!users) {
	return (
		<Redirect to=“/abc” />
	)
}
return (
	div…

근데 Link도 to prop 있는거 아닌가...? 에 대한 답변...근데 플젝에서 직접 써봐야 이해가 갈것같다ㅜㅅㅜ

https://stackoverflow.com/questions/51116747/react-router-link-vs-redirect-vs-history

 

React-Router - Link vs Redirect vs History

There seems to be some confusion with what to use over the other: history.push('/some/path') I have been using React/Router for a li...

stackoverflow.com

  • Switch 안에서 쓰일 경우, from과 to를 받아서 이동하게 만듦
    • ex) from "/" to="/login"

5. Link, NavLink(Link 특별한 버전!)

  • to prop을 특정 URL로 받아, 클릭 시 네비게이션 함
  • anchor tag를 래핑함
  • NavLink의 경우, 매칭 시 style attributes를 추가해줄 수 있음  ➡️ Link와 가장 큰 차이점
  • to에 location object나 함수를 받을 수 있음

https://reactrouter.com/web/api/NavLink

 

React Router: Declarative Routing for React

Learn once, Route Anywhere

reactrouter.com

 

6. useHistory, useLocation, useParams, useRouteMatch

  • 최상위 컴포넌트가 아니더라도 hook으로 react-router 관련 객체에 접근할 수 있음
  • history, location, params, match 객체에 접근