React는 SPA이다.
SPA (Single Page Application)
여기서 Application이란? 유저랑 상호작용할 수 있는 웹페이지를 의미한다.
웹페이지 경로마다 브라우저가 HTML을 다운받아서 브라우저 화면에 그려야 하는데,
전체 웹사이트에 HTML이 딱 하나 있으면 그릴 수 있는 웹페이지도 하나밖에 없을 것이라 생각할 수 있다.
React는 HTML 파일이 1개가 존재하지만, UI를 구성하는 코드는 javascript 파일에 있다.
이 파일은 index.html의 태그 중에 id 선택자가 root인 div태그에 DOM으로 연결되어 화면에 그려지므로,
HTML 파일은 하나만 있어도 javascript 파일이 여러개 있으면 MPA 처럼 여러페이지를 브라우저 화면에 나타낼 수 있고, 하나의 웹사이트를 구성할 수도 있다.
이때, 페이지마다 경로를 설정해 줘야 어떤 페이지인지 쉽게 찾아갈 수 있는데,
경로마다 해당 페이지를 브라우저 화면에 출력하는것을 Routing 이라 한다.
React는 UI를 그리는 라이브러리 이기 때문에 Routing 기능이 내장되어있지 않아 설치 후 사용이 가능하다.
그 중 React-Router 라이브러리를 사용할 것이다.
설치방법 : terminal -> npm install react-router-dom 입력
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<StrictMode>
<App />
</StrictMode>
);
//지금까지 컴포넌트는 index.js의 변수 root의 render를 통해 렌더링되었는데
//(이때, root.render메서드로 전달해주는 첫번째 인자가 랜더링 되는 컴포넌트이다.)
설정
- src폴더 안에 Router.js 파일을 만든다.
(App 컴포넌트만 있다면 괜찮지만 다른 화면도 같이 띄워야 하는데 이때, 경로 관리를 편리하게 하기 위해 Router.js파일을 만들어 관리한다.)
- Router.js 파일에 Router 컴포넌트 기본구조 만들기
//Router.js
import React from 'react';
import {BrowserRouter, Routes, Route};
const Router = () => {
return (
<BrowserRouter> //1. BrowserRouter 컴포넌트로 전체를 감싸준다.
<Routes> //2. BrowserRouter 하위에 Routes컴포넌트를 추가한다.
<Route/> //3. 마지막으로 Routes컴포넌트 하위에 Route컴포넌트를 추가한다.
</Routes>
</BrowserRouter>
)
}
export default Router;
//다른 파일에서 import 해야 하기 때문에 export 잊지말기!
BrowserRouter 컴포넌트 | 경로 변경에 대해 여러 편의기능을 제공해 줌. 대표적으로 페이지가 새로고침 되지 않아도 주소변경을 가능하게 하는 기능이 있다. |
Routes 컴포넌트 | 여러 Route 컴포넌트를 감싸는 역할을 함으로써, Route의 지정된 경로와 브라우저 주소창에 입력한 URL 경로가 딱 맞는 컴포넌트가 있으면 그 컴포넌트를 브라우저에 그리는 역할을 한다. |
Route 컴포넌트 | 브라우저에 렌더링 할 컴포넌트와 경로를 지정하는 역할을 함 속성으로 path, element를 부여한다. - Path : 브라우저에 렌더링 할 컴포넌트의 경로를 할당 -Element : 경로에 따라 렌더링 될 컴포넌트를 할당 |
예시로 Main, Login, Signup 컴포넌트를 Router에 할당해 보겠다.
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Login>}/>
<Route path="/signup" element={<Signup>}/>
<Route path="/main" element={<Main}/>
</Routes>
</BrowserRouter>
)
//아무런 경로를 입력하지 않으면 Route가 컴포넌트의 path 속성중에 "/"를 찾아 브라우저 화면에 그리게 되어
//http://localhost:3000 만 입력하면 Login 페이지가 기본으로 화면에 출력된다.
- 만들어진 Router.js 파일을 index.js의 render 메서드 인자로 전달한다.
//index.js
root.render(
<Router />
);
(= 3가지 경로에 해당하는 3가지 컴포넌트를 화면에 그릴 준비 완료 )
경로를 지정하지 않는 Naviation 이나 Footer를 화면에 출력하는 법
일단, Nav 이나 Footer는 어떤 경로에 접근해도 어디서는 화면에 그려지는데,
이 것을 구현하려면 어떻게 해야 할까?
import React from 'react';
import {BrowserRouter, Routes, Route};
import Nav from './componenets/Nav/Nav'
import Footer from './componenets/Footer/Footer;'
//꼭 import 해주기
const Router = () => {
return (
<BrowserRouter>
<Nav/>
<Routes>
<Route path="/" element={<Login>}/>
<Route path="/signup" element={<Signup>}/>
<Route path="/main" element={<Main}/>
</Routes>
<Footer/>
</BrowserRouter>
//Route : 각각 경로와 화면에 나타낼 컴포넌트를 지정했다면
//Routes 밖 : URL의 영향을 받지않고 브라우저에 항상 보이게 된다.
)
}
export default Router;
React-Router에서 클릭으로 경로를 이동하는 방법
1. Link 컴포넌트
: React-Router-Dom 이 제공하는 컴포넌트 중 하나
사용방법
//Login.js
import React from 'react';
import {Link} from 'react-router-dom';
//먼저 react-router-dom 에서 Link 컴포넌트를 import 한다.
function Login() {
return <h1>Hello! Login!
<Link to="/signup">signup 으로 이동!</Link>
</h1>}
// Click 해서 경로를이동할 부분에 Link 컴포넌트를 만들고 to (props)를 선언하고 경로를 할당하면 된다.
// Link 컴포넌트로 만든 부분을 누르면 URL 경로가 바뀌면서 해당경로로 지정된 컴포넌트가 화면에 그려진다.
// 다른 연산과정 없이 페이지를 이동할 때 쓰인다.
export default Login;
2. useNavigate hook 이용
//Signup.js
import React from 'react;
import {useNavigate} from 'react-router-dom';
//import 꼭 하기!
function Signup() {
const navigate = useNavigate();
//선언된 navigate는 useNavigate가 반환한 함수이므로 소괄호 () 를 붙여서 함수호출을 할 수있다.
//navigate('/main') <- 소괄호 안에 인자로 이동할 경로를 string 타입으로 적어주면 경로로 이동할 수 있다.
return<h1>Signup</h1>;
}
export default Signup;
* Link 컴포넌트는 조건없이 클릭만 하면 이동
* useNavigate hook 은 조건이 필요한 곳에서 navigate 함수를 호출해서 경로를 이동할 수 있다.
위 코드에서
버튼을 만들고 이벤트 속성을 부여해 보았다.
import React from 'react';
import {useNavigate} from 'react-router-dom';
function Signup(){
const navigate = useNavigate();
return (
<h1>
Signup
<button onClick={()=> {
navigate(".main");
}}>메인으로 이동!
</button>
</h1>
);
}
왜 useNavigate를 직접 호출하지 않고 변수로 선언해서 반환된 함수를 호출했을까??
: 'useNavigate는 hook' 이라서 이다.
: react 공식 문서에서 hook은 컴포넌트의 최상단에서만 호출해야 한다고 한다.
그래서 조건문, 함수선언문, 반복문 등 중첩된 함수 안에서 호출할 수 없다.
=> 컴포넌트 내부 함수에서 callback으로도 호출할 수 없다.
=> 함수 컴포넌트에서만 호출할 수 있다.
: 어떤 함수에서 경로 이동을 위해 useNavigate hook을 호출하면 함수의 {} 안에서 호출되기 때문에 규칙에서 어긋나지 않는다.