47일차(2)/React(13) : SPA(Single Page Application) 예제
- react-router-dom 기능 사용하기 (NavLink, Route, withRouter)
- 컴포넌트의 property 로 제공되는 location, match, history 사용하기
- queryString 기능 사용하기
- React로 웹페이지 전체를 만들면(SPA) 응답 방식도 전부 바뀐다.
전체 페이지가 달라지지 않으므로(페이지 이동 X) json으로만 응답하게 된다.
- spa_app 새 리액트 앱 생성
(.css 등 필요없는 파일은 지우기)
App.js
import { NavLink, Route, withRouter } from "react-router-dom";
import { Home, Study, Game, Buy } from "./pages";
function App({location, match, history}) {
//active 되었을때 어떤 css를 적용할지 미리 정한 다음 적용시킬 수 있다.
const activeStyle = {
color:"red",
fontWeight:"bold"
}
return (
<div className="App">
<h1>React Router</h1>
<button onClick={()=>{
//함수의 인자로 전달받은 history객체의 push함수를 이용해서 이동할 수 있다.
history.push("/study");
}}>공부하러 가기</button>
<ul>
<li><NavLink activeStyle={activeStyle} to="/">home</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/study">study</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game">game 홈</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/starcraft">game starcraft</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/mario">game mario</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/buy?code=1&name=handphone">1번 상품구매</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/buy?code=2&name=water">2번 상품구매</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/buy?code=3&name=coffee">3번 상품구매</NavLink></li>
</ul>
<Route exact path="/" component={Home}/>
<Route exact path="/study" component={Study}/>
<Route exact path="/game" component={Game}/>
{/* name 이라는 이름의 경로 파라미터를 읽을 수 있도록 설정 */}
<Route path="/game/:name" component={Game}/>
<Route path="/buy" component={Buy}/>
</div>
);
}
//withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.
export default withRouter(App);
- 어떤 링크를 누르면 이 아래쪽 빨간 박스에 해당 컨텐츠만 나오도록 하려고 한다.
- 기존의 페이지 전환 방식은 home.jsp 등으로 페이지 이동이 일어난다. 다른 경로를 가진 페이지가 처음부터 로딩된다.
- 이번에는 페이지를 이동하지 않는 링크를 만들고자 한다!
- 페이지의 일부만 수정해서 누르는 링크에 맞는 컨텐츠를 아래 보여주는 방식으로 한다.
- npmjs.com에서 검색. react-router-dom 을 설치해서 사용할 예정이다.
- 위와 같이 json 폴더에 입력하는 것만으로도 설치할 수 있다.
- 설치하려는 이름을 입력하고 npm install 하면
자동으로 package.json의 dependencies를 찾아서 이중에서 설치되지 않은 것을 설치해준다.
- 12개의 패키지가 설치되었다고 나온다!
- 다시 한 번 npm install 하면 up to date라고 나온다. 현재 dependencies에 있는 모듈들이 다 설치되어 있다는 뜻!
- src에 root.js 파일 생성
//root.js
import { BrowserRouter } from "react-router-dom";
import App from "./App";
const Root = () => {
return(
<BrowserRouter>
<App />
</BrowserRouter>
);
}
//App을 감싼 BrowserRouter를 렌더링해주는 Root component 리턴해주기
export default Root
- 이제 브라우저 라우터를 쓸 수 있다. Root에서 import하기
<BrowserRouter>
<App />
</BrowserRouter>
- return 안에 위 코드를 작성해준다.
- App을 BrowserRouter로 감싸서 리턴해준다고 생각하면 된다.
- index.js도 App에서 Root로 바꿔주기
- App 함수에 obj 변수를 넣으면 object 가 하나 전달되는 것을 확인할 수 있다.
- NavLink import 해주기
- NavLink도 react-router-dom 에 들어 있다.
- 클릭해도 페이지가 바뀌지는 않지만, 주소창의 경로가 달라지는 것을 볼 수 있다.
- console창을 확인해보면 <a> anchor로 바뀌어 있는 것을 볼 수 있다.
- navLink는 javascript가 동작하는 링크로 달라진다는 것을 알 수 있다.
src 안에 pages 폴더 - 안에 Home.js / Game.js / Study.js 만들어주기
Home.js
// pages/Home.js
const Home = ()=>{
const homeStyle={
backgroundColor:"pink",
height:"300px"
};
return(
<div style={homeStyle}>
<h3>home 페이지 입니다.</h3>
<p>어쩌구 저쩌구...</p>
</div>
);
}
export default Home;
Study.js
// pages/Study.js
import { NavLink } from "react-router-dom";
const Study = ()=>{
const studyStyle={
backgroundColor:"yellow",
height:"300px"
};
return(
<div style={studyStyle}>
<h3>study 페이지 입니다.</h3>
<p>어쩌구 저쩌구...</p>
<NavLink to="/">홈으로</NavLink>
</div>
);
}
export default Study;
Game.js
// pages/Game.js
const Game = ({match})=>{
const gameStyle={
backgroundColor:"green",
height:"300px"
};
// "/game/:name" 의 name을 읽어오기
let gameName=match.params.name; //경로 파라미터
if(!gameName){
gameName="기본";
}
return(
<div style={gameStyle}>
<h3>game 페이지 입니다.</h3>
<p><strong>{gameName}</strong> 게임을 시작합니다.</p>
</div>
);
}
export default Game;
- 현재 pages 폴더 안에 여러 개의 파일이 들어가 있으므로,
해당 폴더를 폴더째로 import하고, 그 안의 특정요소를 export해서 편리하게 사용할 수 있도록 한다!
- 이 통합파일의 이름은 정해져 있다. index.js (소문자로 시작) - 최종본
// pages/index.js
//pages 폴더를 import 해서 Home, Study, Game, Buy 을 모두 사용할 수 있도록 설정
export { default as Home } from './Home';
export { default as Study } from './Study';
export { default as Game } from './Game';
export { default as Buy } from './Buy';
import { Home, Study, Game } from "./pages";
import{ 파일명1, 파일명2, 파일명3 } from "/폴더명(경로)";
- 그리고 App.js에 위와 같이 import 해주면 된다.
- 폴더명 하나로 전체 import 가능!
- 페이지 주소(경로)는 달라지지만 그렇게 보이지 않는다.
- 전체를 새로고침하는 것 같은 변화가 없다. 해당 부분만 달라진다.
- 각각의 컴포넌트에서 각각의 ui, 동작, 함수 등을 가질 수 있다.
- 이전에는 <a>로 페이지를 이동했지만 이렇게 하면 UI는 달라지지만 컨텐츠만 바뀌고 페이지 이동은 일어나지 않는다.
- 링크 클릭시 지정한 component로 change되는 것이다.
- 만약 글 목록보기(DB) 등이 필요한 경우 페이지 전환 없이, 서버에 ajax 요청을 통해서 가지고 온다.
- 이렇게 만드는 것이 Single Page Application이다.
<ul>
<li><NavLink activeStyle={activeStyle} to="/">home</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/study">study</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game">game</NavLink></li>
</ul>
< NaviLink activeStyle={ style명 } > 설정
- active 효과를 주는 class를 부여하는 것과 같이,
active 되었을때 어떤 css를 적용할지 미리 정한 다음 적용시킬 수 있다
- 해당 페이지가 active 되었을 때 폰트에 수정된 스타일이 적용된다.
- withRouter 적용하기 (import)
//withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.
export default withRouter(App);
export default withRouter(컴포넌트명);
- withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.
- 위에서 매개변수에 전달된 obj값을 콘솔에서 확인하기!
- object가 전달되고, history, location, match 라는 방 이름이 있다.
- 이것을 사용하려면 obj.history 형태로 사용하면 된다.
- 구조분해 할당으로 받아서 사용할 수도 있다.
- 이 object가 여기로 전달되는 것이다.
function App({location, match, history}) { }
- obj의 history, location, match 방 안에 들어있는 {...} 값을 저 { , , } 안에다가 각각 할당하는 것
<li><NavLink activeStyle={activeStyle} to="/game">game 홈</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/starcraft">game starcraft</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/mario">game mario</NavLink></li>
- NavLink 추가해줌. 하위 경로가 생겨난다. 페이지 변화는 없지만(새로고침 X) 해당 경로로 이동한다.
- game 컴포넌트에서 to="" 를 읽어와서 여기에 있는 내용을 사용할 수 있다.
game.js 수정하기
const Game = ({match})=>{ }
let gameName=match.params.name;
- match만 구조분해할당 해주고 경로를 읽어오는 gameName 변수 추가
- match.params.name; 으로 읽어오는 이것을 경로 파라미터라고 부른다.
<Route path="/game/:name" component={Game}/>
- App.js에 위 내용을 추가해준다.
- name 을 component로부터 읽어내서 뒤의 주소로 이동(페이지이동x) 하게 한다.
- 특정 경로(game) 내의 주소가 바뀌면 아래 보이는 텍스트(게임 이름)도 달라진다.
- param으로 읽어온 값이 보여주는 UI인 것!
buy.js 생성. 구매 페이지
// pages/buy.js
import queryString from "query-string";
const Buy = ({location})=>{
//location을 구조분해 할당 받아서 search 라는 방에 있는 문자열 확인하기
console.log(location.search);
//queryString 함수를 이용해서 query 문자열을 파싱해서 object 얻어내기
const parsed=queryString.parse(location.search);
console.log(parsed);
const buyStyle={
backgroundColor:"#cecece",
height:"300px"
};
return(
<div style={buyStyle}>
<h3>Buy 페이지 입니다.</h3>
<p>
<strong>{parsed.code}</strong>번 상품
<strong> {parsed.name}</strong>을 주문 하였습니다.
</p>
</div>
);
}
export default Buy;
const Buy = ({location})=>{ }
- location 을 구조분해로 할당받는다.
- index.jsp에 새로 생성한 buy도 빼내주기
console.log(location.search);
- 콘솔창에 구매하는 내용이 기록된다.
- 이 중에서 code와 name 값만 뽑아내서 분리하려면?
- npm에서 install하기
- query-string : 위와 같은 쿼리 문자열에서 필요한 내용을 추출하는 도구
- 사용방법: import해서 parse하면서 location.search 에서 읽어온 값을 사용한다.
- object 형태로 추출되므로 . 점 찍어서 빼내서 사용할 수 있다.
- 설치
const parsed=queryString.parse(location.search);
- parse 기능으로 담아서 사용하기
- 위와 같은 값을 읽어서 {} 안에 넣으면 아래와 같이 만들어준다!!
- 방을 분리해서 object의 형식에 넣어준다.
- query string을 사용한 값을 읽어와서 화면에 이렇게도 표시할 수 있다.
- 이 값(패러미터)을 읽어와서 페이지의 일부 내용을 변화시킬 수 있는 것.
- 이클립스로 만들었던 게시판의 글 자세히 보기(detail) 등의 기능에서도 해당 내용을 적용 가능하다.
* in jsp page
/cafe/detail.jsp?num=1
→ num=1이 주소인 페이지로 페이지가 바뀌면서 request.getParameter("num") 으로 읽어와서 처리했음
* in React js
/cafe/1 또는 /cafe/detail?num=1
→ 페이지 전환 없이 일부만 바꾸어 보여주는 처리들을 할 수 있다.
- study.js로 바로 이동하는 버튼 생성
- history를 사용해 버튼 클릭시 특정 페이지로 이동시키기
- 라우터의 history.push() 를 사용해서 특정 경로로 이동할 수도 있다.
- 기존 javascript 의 location.href=" "; 와 같은 기능
- study 페이지에 돌아오는 링크 추가
<NavLink to="/">홈으로</NavLink>
- study.js 페이지에서 navLink 사용해서 홈으로 이동하기
- 위와 같이 SPA를 사용하면 페이지 전환 없이도 특정 어플리케이션을 생성할 수 있다.
'국비교육(22-23)' 카테고리의 다른 글
48일차(2)/Spring(1) : java, maven, STS 설치 및 기본 세팅 (1) | 2022.12.15 |
---|---|
48일차(1)/React(14) : SPA(Single Page Application) 예제(2) (0) | 2022.12.14 |
47일차(1)/React(12) : jsp 웹페이지 React 로 재작성하기 (회원가입 폼) (0) | 2022.12.13 |
46일차(3)/React(11) : React 에서 만든 결과물 배포하기(build) (0) | 2022.12.12 |
46일차(2)/React(10) : import, export 활용 예제(module) (0) | 2022.12.12 |