TIL 17 | React Router

15658 단어 ReactReact

React Router

1. SPA <-> MPA

SPA란?

  • Single Page Application (싱글 페이지 어플리케이션) 의 약자이다. 말 그대로, 페이지가 한 개인 어플리케이션이다.

  • 하지만! 리액트 프로젝트에서는 html 페이지를 1개로 만드려고 한다.
    ➡️ SPA(Single Page Application)

  • 이전에 내가 작성한 html은 Login.html, main.html 과 같이 페이지 수만큼 html 파일이 존재한다.

  • Routing : 하나의 웹 페이지 안에서 여러 페이지를 보여주는 방법이다.

2. Routing

Routing의 사전적 의미 : 경로.

Routing:

  • 프론트엔드 입장에서는 특정 경로에서 특정 화면을 보여주는 것.
  • 즉, 다른 경로(url 주소)에 따라 다른 View(화면)을 보여주는 것이다. (eg. /login, /main)
  • 리액트 자체에 내장되어 있는 기능은 아니다.
  • 즉, 이러한 이유로 리액트가 Framework가 아닌 Library로 분류된다.

  • 필요하지만 없는 기능은 외부 라이브러리에서 Framework 안에 설치하면된다.

  • React-router 는 리액트의 라우팅 기능을 위해 가장 많이 사용되는 라이브러리이다. (외부 라이브러리: Third-party Library)

  • CRA는 라이브러리다...! 그래서 React Router를 설치해야한다.

3. React Router

  • Create React App(CRA)에 특별히 routing을 위한 로직이 없다.
  • routing을 위한 패키지가 없는 이유는 React는 UI만 담당하기 때문이다.
  • routing solution인 react-router(외부 패키지) 를 추가해서 routing을 구현해야한다.

3-1. 설치 방법

npm install react-router-dom --save 를 터미널에 입력한다.
➡️ --save 넣으면, package.json의 dependencies에 추가된다.

설치했을 때 오류메세지가 없어야하는데, 나는 아래와 같은 메세지를 확인했다.

⬇️ node_modules에서도 react-router가 보이지 않았다 😇

⬇️ 그런데 package.json 파일에선 react-router-dom이 보인다..

VSC말고 iterm에서 다시 해보았더니 다시 잘 깔려서 사용가능 !

3-2. Route 컴포넌트의 구성 요소(return 문 안에서)

import React from 'react'; // node_modules의 react에서 가져온 React
import {
  BrowserRouter as Router, // BrowserRouter를 Router라고 부를거야 하고 이야기하는 것
  Switch,
  Route,
} from 'react-router-dom';

✔️<Router /> : 라우팅 기능을 위해서 감싸주는 컴포넌트

✔️ <Switch /> : 경로에 따라 어떤 컴포넌트가 보여지게 되는지 지정

✔️<Route /> : 실제 경로와 실제 보여주는 컴포넌트 지정

세 가지 요소가 모두 있어야 Routing이 된다.

exact 속성 : 정확한 경로를 찾아줘 ! 라는 의미이다.
➡️ exact path = "/" : url경로를 /(defualt)로 정했을 땐 Login 컴포넌트 실행
➡️ exact path = "/main" url경로를 /main로 정했을 땐 Main 컴포넌트 실행

✔️ import 해주었으면 꼭 export 해주기 !

📍 알아두면 좋을 것!
하나의 컴포넌트가 다른 컴포넌트에 중복적으로 사용될때는 어떻게 해야할까?
➡️ Router.js의 <Router />의 자식 요소로 넣어주면, <Switch /> 안의 <Route />에 각각 적용된다.!

➡️ 예를 들어 Nav.js가 Login.js 와 Main.js의 컴포넌트로 중복사용하게 된다면?

import Nav from './components/Nav'; // 잊지말고 import 해주기

class Routes extends React.Component {
  render() {
    return (
      <Router>
	<Nav /> // 여기에 Nav 컴포넌트 적어주기!
        <Switch>
          <Route exact path="/" component={Login} />
          <Route exact path="/main" component={Main} />
        </Switch>
      </Router>
    )
  }
}

export default Routes;

3-4. Route 이동하기

Route 이동하는 방법은 두 가지가 있다.

1. <Link /> 컴포넌트 사용하는 방법

✔️ 링크 원하는 컴포넌트(eg. Login.js)에 import { Link } from 'react-router-dom'; 적어준다 !!

✔️ <Link/> 태그로 감싼 뒤, property to 사용한다.

📍 알아두면 좋을 것 !
<Link> 컴포넌트란?

: <a> 태그와 같은 기능을 한다.
: react-router-dom 에서 제공하는 <Link> 컴포넌트는 DOM에서 <a> 로 변환(Compile)

📍 알아두면 좋을 것 !
<a> 태그와 <Link>의 차이점 : 효율성을 위해서 나누어서 사용함.

  • <a> - 외부 사이트로 이동하는 경우 : 완전히 전환될 때 사용함. 내부이동 때는 사용하지 않지만, 완전히 외부로 이동할 때 사용함.
  • <Link> - 프로젝트 내에서 페이지 전환하는 경우 : a로 컴파일 되지 만 새롭게 파일을 받아오는 요청을 하지 않음. 경로만 바꿔줌. 필요 없는 부분 렌더링 하지 않음.

✏️ <Link> 컴포넌트를 실습해 보았다. (Login page의 버튼을 누르면, Main page로 이동하기)

나의 코드

<form action="">
 <input type="text" id="loginId" placeholder="전화번호, 사용자 이름 또는 이메일" />
 <input type="password" id="loginPw" placeholder="비밀번호" />
 <Link to="/main">
  <button type="button" className="loginBtn">로그인</button>
 </Link>
</form>

다른 스타일링은 적용이 되지만, form에 display:flex; 속성을 부여한 것이 반영되었다. <Link> 컴포넌트를 사용하면서 button 태그가 자식요소에서 벗어났기 때문에 display:flex; 속성이 적용되지 않은 것이다.

➡️ 해결방법 1) button 태그에 width: 100%를 적어주면 해결된다.
➡️ 해결방법 2) <Link> 컴포넌트 자체에 className을 부여해서 스타일을 적용한다.

2. withRouterHOC (Higher Order Component) 로 구현하는 방법

✔️ 링크기능을 원하는 컴포넌트(eg. Login.js)에 import { withRouter } from 'react-router-dom';적어준다 !!

✔️ export 원하는 컴포넌트를 withRouter로 감싼다. export default withRouter(Login); : 특정 기능을 넣기 위해 감싸는 것이다.

즉, this.props.history.push('/') 를 사용하기 위해서 사용하는 것이다.

// goToMain => 함수명은정하기나름 !
 goToMain = () => {
   this.props.history.push('/main');
 }
  • this : 지금 단계에선 이해하기 어렵지만, class안에서 this가 있다면 무조건 () => {} arrow function 으로 써줘야 내가 class로 만든 컴포넌트를 사용할 수 있다.

  • 일반 fucnction을 사용하면 this가 시시각각 변할 수 있기 때문이다.

  • props : 객체

  • history : 객체

  • push() : 함수 (메서드)

  • 이 함수가 실행하는지 확인하려면...? 콘솔찍어보기 ^^ㅎ


    😲 render() 도 함수이니까 console.log 확인기 가능하다...!

    console을 확인해보니, histroy -> push(); 가 있는 것을 알 수 있었다.

    🔥 이렇게 Login.js에는 this.props.history.push('/') 함수 가 있는 이유는 <Switch /> 안에 감싸여 있는 컴포넌트이기 때문이다.

    🔥 다시 한번 말하자면, 만약 <Switch />에 감싸여 있지 않은 컴포넌트에 this.props.history.push('/') 함수가 필요하다면, withRouter로 감싸주면 된다!

✏️ withRouterHOC 실습

  • <Link> 컴포넌트를 실습할 때와는 다르게 태그를 직접 입력하는 것이 아닌 button 태그 자체에 onClick 이라는 이벤트를 넣었기 때문에 구조상 변동이 없어서 사용한 SCSS 태그가 망가지지 않고 잘 적용되는 보습을 보인다.

3. Link 와 withRouter의 차이점

✔️ Link : 클릭 시, 바로 이동하는 로직 구현 (a 태그와 유사한 성격)

✔️ withRouter : 추가로 처리해야하는 로직이 있는 경우
➡️ 함수호출 형태를 사용하면, 조건문을 넣을 수 있다.
➡️ 특정 조건이면 이동 하는 경우에 대한 옵션 제공.

// 백엔드와 통신을 하거나, 추가로 다른 로직을 해야할 때 사용한다.
 goToMain = () => {
  if(response.message === "valid user"){
    this.props.history.push('/main');
  } else {
    alert("너 우리 회원 아님. 가입 먼저 해주세요")
    this.props.history.push('/signup');
   }
 }

4. ✏️ 리액트를 배우고

생소한 개념이라 받아들이기 쉽지않지만, 익숙해지면 정말 편리해질 것이라는 생각이 드는 세션이었다. 여러 컴포넌트를 만들어두고 가져오기만하면 하나의 html로 페이지를 구성할 수 있다니...! 열심히 배워봐야겠다.🙌🏻

좋은 웹페이지 즐겨찾기