Single Page Application (싱글 페이지 어플리케이션) 의 약자이다. 말 그대로, 페이지가 한 개인 어플리케이션이다.
하지만! 리액트 프로젝트에서는 html 페이지를 1개로 만드려고 한다.
➡️ SPA(Single Page Application)
이전에 내가 작성한 html은 Login.html
, main.html
과 같이 페이지 수만큼 html 파일이 존재한다.
Routing : 하나의 웹 페이지 안에서 여러 페이지를 보여주는 방법이다.
Routing의 사전적 의미 : 경로.
Routing:
필요하지만 없는 기능은 외부 라이브러리에서 Framework 안에 설치하면된다.
React-router 는 리액트의 라우팅 기능을 위해 가장 많이 사용되는 라이브러리이다. (외부 라이브러리: Third-party Library)
CRA는 라이브러리다...! 그래서 React Router를 설치해야한다.
npm install react-router-dom --save
를 터미널에 입력한다.
➡️ --save 넣으면, package.json의dependencies
에 추가된다.
설치했을 때 오류메세지가 없어야하는데, 나는 아래와 같은 메세지를 확인했다.
⬇️ node_modules에서도 react-router가 보이지 않았다 😇
⬇️ 그런데 package.json 파일에선 react-router-dom이 보인다..
VSC말고 iterm에서 다시 해보았더니 다시 잘 깔려서 사용가능 !
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;
Route 이동하는 방법은 두 가지가 있다.
<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을 부여해서 스타일을 적용한다.
✔️ 링크기능을 원하는 컴포넌트(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 태그가 망가지지 않고 잘 적용되는 보습을 보인다.✔️ Link : 클릭 시, 바로 이동하는 로직 구현 (a 태그와 유사한 성격)
✔️ withRouter : 추가로 처리해야하는 로직이 있는 경우
➡️ 함수호출 형태를 사용하면, 조건문을 넣을 수 있다.
➡️ 특정 조건이면 이동 하는 경우에 대한 옵션 제공.
// 백엔드와 통신을 하거나, 추가로 다른 로직을 해야할 때 사용한다.
goToMain = () => {
if(response.message === "valid user"){
this.props.history.push('/main');
} else {
alert("너 우리 회원 아님. 가입 먼저 해주세요")
this.props.history.push('/signup');
}
}
생소한 개념이라 받아들이기 쉽지않지만, 익숙해지면 정말 편리해질 것이라는 생각이 드는 세션이었다. 여러 컴포넌트를 만들어두고 가져오기만하면 하나의 html로 페이지를 구성할 수 있다니...! 열심히 배워봐야겠다.🙌🏻