2023. 4. 10. 11:10ㆍReact/실전 리엑트 프로그래밍
📘 리액트 프로젝트 시작하기
✅ 리액트란 무엇인가?
- 페이스북에서 개발하고 관리하는 UI 라이브러리
- 리액트는 UI 기능만 제공 ( 앵귤러가 웹앱 개발에 필요한 다수의 기능을 제공하는 것과는 달리)
따라서 전역상태관리, 라우팅, 빌드 시스템 등을 각 개발자가 직접 구축해야한다.
- 전반전인 시스템을 직접 구축하기 때문에 자유롭다는 장점이 있지만, 개발 환경을 직접 구축해야하는 번거로움이 있다.
- 리액트 팀에서 create-react-app이라는 툴을 제공해서 어느정도 이 단점을 보완해준다.
- 프론트엔드 프레임워크를 사용하는 이유는?
자동으로 UI를 업데이트 해준다는 장점!
UI = render(state) 라고 함축적으로 표현할 수 있다.
- render 함수는 순수함수로 작성하는 것이 좋다.
- 순수함수는 입력값이 같으면 출력값이 같다는 특징
- 혹은 render 함수 내부에서 외부 상태를 변경하게 되면 다른 render함수의 출력값에 영향을 줄 수 있다. (하지 않는게 좋다) - state는 불변 변수로 관리하는게 좋다.
- 이렇게 코드에서 순수함수와 불변변수로 관리하게 되면 복잡도가 낮아지고 버그 발생 확률도 줄어든다.
- 또한 리액트 내에서 이 조건을 따른다면 렌더링 성능을 크게 향상 시킬 수 있다.
- 리액트의 또 다른 장점은 가상돔(virtual dom)을 이용해 빠르게 UI를 업데이트한다.
- 가상돔은? 이전 UI 상태를 메모리에 유지해서 변경된 부분만 실제 DOM에 반영해주는 기술
✅ 리액트 개발 환경 직접 구축하기
function LikeButton() {
const [liked,setLiked] = React.useState(false); // 기본값은 false
const text = liked ? '좋아요 취소' : '좋아요';
// createElement는 리액트 요소를 반환함
return React.createElement(
'button',
{ onClick:()=>setLiked(!liked) },
text,
)
// 문자열로 입력하면 html로 해당하는 태그가 만들어진다.
// likeButton 이라는 컴포넌트가 완성됨
}
// div안에 렌더링을 하기위한 작업
const domContainer1 = document.getElementById('root1');
// 렌더링 부분
ReactDOM.render(React.createElement(LikeButton),domContainer1)
// 컴포넌트를 렌더링할때도 마찬가지로 리액트 요소로 만들어준다.
- createElement()
React.createElement(
'button',
속성 값,
// 두번째요소는 속성값, 우리는 onclick이라는 이벤트 핸들러가 표현
children,
// 버튼의 children으로 텍스트를 출력
)
- useState는 컴포넌트의 상태값을 추가할때 사용한다.
- React는 react.development.js가 실행될때 전역변수로 노출됨
- 리액트에서는 리액트를 표현하는 가장 작은 단위가 리액트 요소라고 보면 된다.
- ReactDom도 마찬가지로 react-dom.development.js이 실행될때 전역변수로 노출이 된다.
createElement를 이용해 다음과 같은 구조의 엘리먼트를 생성하고 싶다면?
<div>
<p>hello</p>
<p>world</p>
</div>
const helloEl = React.createElement(
'div',
null,
React.createElement('p',null,'hello'),
React.createElement('p',null,'world'),
)
ReactDOM.render(helloEl,domContainer);
DOM 여러 요소에 렌더링해보기
html을 다음과 같이 마크업 하고
<h3>root1</h3>
<div id="root1"></div>
<h3>root2</h3>
<div id="root2"></div>
<h3>root3</h3>
<div id="root3"></div>
// 루트1
const domContainer1 = document.getElementById('root1');
ReactDOM.render(React.createElement(LikeButton),domContainer1);
// 루트2
const domContainer2 = document.getElementById('root2');
ReactDOM.render(React.createElement(LikeButton),domContainer2);
// 루트3
const domContainer3 = document.getElementById('root3');
ReactDOM.render(React.createElement(LikeButton),domContainer3);
- 각각의 상태값을 갖고있는 컴포넌트가 렌더링된다.
- 레거시 프로젝트를 리액트로 조금씩 포팅할때 이런 사용법 사용한다.(?)
- but 이렇게 세개를 렌더링한다면 보통 리액트 안에서 해결하는 것이 좋다.
리액트 안에서 버튼 렌더링해보기
아까와는 모습이 조금 다르지만 얼마든지 리액트 안에서도 수정할 수 있다는 모습을 보여준다.
// 좋아요 버튼
function LikeButton() {
const [liked,setLiked] = React.useState(false);
const text = liked ? '좋아요 취소' : '좋아요';
// createElement는 리액트 요소를 반환함
return React.createElement(
'button',
{ onClick:()=> setLiked(!liked) },
text,
)
// 브라우저에 렌더링
const domContainer = document.getElementById('root');
ReactDOM.render(
React.createElement('div',
null,
React.createElement(LikeButton),
React.createElement(LikeButton),
React.createElement(LikeButton)
),domContainer
)
✅ 바벨 사용해보기
- 초기의 ES6 문법을 ES5 문법으로 변환해주는 용도로 사용
- 최근에는 코드의 주석을 제거하거나, 코드를 압축하는 용도같은 다양한 용도로 사용
- 리액트에서는 jsx의 문법을 createElement함수를 호출하는 코드로 변환하기 위해서 바벨을 사용한다.
createElement 문법을 jsx 문법으로 변환
function LikeButton() {
const [liked,setLiked] = React.useState(false);
const text = liked ? '좋아요 취소' : '좋아요';
return <button onClick={() => setLiked(!liked)}>{text}</button> // jsx 문법
}
function Container() {
const [count,setCount] = React.useState(0);
// jsx 문법
return (
<div>
<LikeButton></LikeButton>
<div>
<span>현재 카운트:</span>
<span style={{ marginRight : 10 }}>{ count }</span>
<button onClick={()=> setCount(count+1)}>증가</button>
<button onClick={()=> setCount(count-1)}>감소</button>
</div>
</div>
)
const domContainer = document.getElementById('root');
ReactDOM.render(React.createElement(Container),domContainer)
jsx 문법으로 변환했을때 다음과 같은 SyntaxError가 발생
Uncaught SyntaxError: Unexpected token '<'
- jsx 문법은 자바스크립트 표준이 아니기 때문에 브라우저에서 실행하면 에러가 남
- 에러가 나지 않도록 바벨을 이용해서 createElement 코드로 변환해줘야한다.
바벨 설치
npm으로 패키지를 관리할때는 package.json이 필요하다.
- package.json 설치
$ npm init -y
- 바벨 설치
$ npm install @babel/core @babel/cli @babel/preset-react
- @babel/core 는 바벨의 핵심 기능을 가지고 있는 패키지
- @babel/cli는 cli에서 사용할 바이너리가 들어있다.
- @babel/preset-react는 리액트를 위한 플러그인 여러개를 모아놓은것
- 바벨에는 프리셋과 플러그인이라는 개념이 있다.
- 플러그인 : 하나의 변환하는 기능
- 프리셋 : 여러개의 플러그인을 모아놓은 것이 프리셋, 특정 목적을 위해 하나의 프리셋으로 묶어주는 것
컴파일
컴파일을 통해 기존에 있던 위치에 simple.js 파일이 만들어지게 할것이다.
$ npx babel --watch src --out-dir . --presets @babel/preset-react
- 한번만 컴파일을 해주는게 아니라 파일이 변경될때마다 자동으로 컴파일을 해준다.
- src폴더에 있는 것을 현재 폴더로 출력해주고, 프리셋으로 이전에 설치했던 @babel/preset-react을 사용함
컴파일이 완료된 것을 확인
function Container() {
// ...생략
<span style={{ marginRight : 10 , color:'red'}}>{ count }</span>
}
스타일에 color:red 속성을 추가해줬더니
컴파일이 실시간으로 완료된 것을 터미널로 확인되고
컴파일본에 스타일 속성이 추가된 것이 확인된다.
npx babel
- ./node_moduls/.bin를 보면 babel이 보인다.
- .bin폴더는 바이너리 파일만 모아놓은 폴더
- 바벨을 설치했기때문에 바벨의 바이너리 파일이 있는것
$ npx babel
- npx 명령어를 입력하면 .bin 폴더에 있는 바벨 바이너리를 실행시켜준다.
- 만약 바벨을 설치하지 않았다면 npx명령어가 바벨패키지를 다운받아서 직접 실행시켜준다.
✅ 웹팩 사용해 보기
- 파일 이름을 기반으로 파일이름에 해시값을 추가해준다.
- 이것은 효율적으로 브라우저 캐싱을 이용할 수 있도록 도와준다. - 사용되지 않는 코드를 제거
- 자바스크립트 파일 압축
- 자바스크립트에서 css나 JSON, 텍스트 파일등을 자바스크립트 모듈처럼 불러올 수 있다.
- 이렇게 자바스크립트 안에서 모든것을 처리할 수 있는 편리한 기능을 제공해준다. - 환경 변수 주입
가장 큰 이유는 모듈 시스템 사용
- 모듈 시스템은 ESM 과 commonJS 가 있다.
- ESM ES6에 추가
- commonJS 노드에서 많이 사용하는 시스템
- 모듈 시스템이란?
- export와 import를 사용한 코드
- ESM문법 - 모듈 시스템 사용법
- default는 괄호 없이 사용
- 중괄호로 가져와서 as를 이용해 이름 변경 - 기존 코드 사용시 문제점
- 자바스크립트가 동적으로 변하면서 자바스크립트 파일이 많아짐
- 글로벌 변수 충돌 가능성
- 외부 라이브러리 사용시
만약 웹팩을 사용한다면 변수 이름 충돌 같은 문제를 빌드 단계에서 잡아낼 수 있다.
외부라이브러리는 npm으로 관리할 수 있고, 그것들이 번들링 단계에서 하나의 파일로 합쳐지면서 앞서 말한 여러가지 문제들이 해결된다.
- 요즘 브라우저에서 ESM을 지원
- 웹팩 없이 ESM 사용해서 서비스
- but 가능은 하지만, 오래된 브라우저도 지원을 해야한다는 문제가 있고, 많은 오픈소스가 commonJS로 작성됐다는 것 - 요즘 브라우저는 commonJS는 처리를 못하기 때문에 웹팩을 사용해야 한다.
요즘 브라우저에서 ESM이 동작한다는 것
<script type="module" src="index.js">
- type="module"로 줄 경우 ESM으로 동작
- index.js로 연결된 a,b,c.js 코드들이 있고 이 파일들을 가지고 실습함.
serve 패키지 사용해서 연결 (직접 브라우저 연결시 에러 발생 가능성있기 때문)
$ npx serve
- 로컬에 있는 파일을 정적파일로 서비스하는 동작, 브라우저로 경로로 접근할 수 있다.
- 콘솔 네트워크 창에서 확인해봤을때 index, a, b, c 자바스크립트 파일이 연결된 것이 확인.
- index 파일만 스크립트로 연결했는데 나머지 파일도 잘 받아온 것을 확인
웹팩 다뤄보기
index.js 이 코드를 웹팩을 이용해서 하나의 파일로 번들링 할 것임
$ npm install webpack webpack-cli react react-dom
- 웹팩을 설치
- webpack
- webpack-cli
- react,react-dom 리액트 패키지
다음은 웹팩을 실행
$ npx webpack
- 웹팩을 실행하면 dist폴더가 생성되고 그안에 번들링된 파일이 생긴다.
- 파일의 코드를 보면 굉장히 복잡하다. 이 안에 리액트 파일도 포함되어 있다.
- 브라우저를 실행하면 렌더링이 잘 되는 것이 확인된다.
- 이전에는 웹에서 리액트를 다운받아서 사용했다면,
- 웹팩을 사용하게 되면서 즉 모듈시스템 을 사용할 수 있게 되면서 npm으로 인스톨해서 사용할 수 있게 된 것이다.
- 그렇기때문에 index.js에서 가져다 쓰는 파일이 모두 하나의 파일로 압축되어 사용할 수 있다.
✅ create-react-app으로 시작하기
- create-react-app은 리액트의 개발환경을 구축해주는 도구
- 리액트의 개발환경을 직접 구축하려면 많은 지식이 필요
예를들어,
- 빌드시스템을 구축하기 위해서 웹팩이나 바벨을 사용해야함
- 테스트환경 - jest 테스트 프레임워크 사용
- 코딩 컨벤션을 정하고 자동으로 체크하기 위해서 eslint를 사용
- 오래된 브라우저 지원하기 위해 polyfill
- HMR 코드릉 수정하면 바로바로 화면에 적요이 되는 기능 -> 개발 생산성 높아짐
- css 후처리 , scss 를 사용하면 css 컴파일 과정이 필요
- 페이스북에서 관리하는 툴
이러한 환경들을 create-react-app에서 자동으로 구축해서 제공해준다.
cra를 이용한 프로젝트 구축
- next.js와 cra 차이
- 서버사이드 렌더링 지원의 차이
- cra 서버사이드 렌더링을 지원x
- 서버사이드 렌더링 지원이 필요하다면 next.js - cra 단점은 빌드시스템이나 eslint 거의 변경할 수 없음
- 설정 변경이 필요하다면 Next.js 바벨 웹팩 estlint 등의 설정을 변경할 수 있음 - 백오피스를 개발할때는 cra로 개발하는게 좋음, 쉽고 빠르다는 장점
cra 설치
$ npx create-react-app cra-test
- react-scripts
- package.json 파일에서 react-scripts라는 명령어를 이용하고 있는데 create-react-app이 버전업이 될때는 대부분 react-scripts의 버전이 올라가는 것이다.
- 때문에 나중에 새로운 버전이 추가됐을때 react-scripts 패키지의 버전만 올려주면 된다. - cra의 설정을 변경할 수 없다고 했는데, 굳이 변경하고 싶다면 react-scripts를 fork한 뒤 수정해서 사용하면 된다.
"browserslist": {
"production": [
">0.2%",
],
- browserslist 브라우저 지원범위에 관한 내용
- polyfill이 어떻게 적용될지 여부를 나타냄
- 0.2% 이상의 점유율을 가진 브라우저를 대상으로 하겠다는 뜻이다.
프로그램 실행
$ npm start
- HMR 기능 덕분에 코드를 수정하면 바로바로 적용됨
- Hot Module Replacement은 응용프로그램 실행 중에 추가 또는 제거된 모듈들을 페이지 리로드 없이 교체하는 기능 - 이렇게 HMR이 동작하는 것은 npm start로 실행했을때 로컬에 서버를 띄워서 브라우저와 통신을 하기 때문에 가능한 것
- npm start 배포시 x 개발모드만, 개발모드기때문에 성능 최적화가 안되어있음
- 배포할 때는 반드시 빌드명령어
- StrictMode
- 개발환경에서 동작하는데 리액트에서 잘못사용한 것들에 대해서 빨리 잡아내기 위해 사용한다. - css나 이미지를 자바스크립트에서 import하는 방식으로 사용하는게 좋다.
- 이미지 경로에 해시값이 들어가기 때문에 브라우저 캐싱을 효율적으로 사용할 수 있다. - 이미지뿐만아니라 데이터를 다룰때 json파일을 사용할 수 있다.
Hot Module Replacement
Hot Module Replacement(HMR)는 모듈 전체를 다시 로드하지 않고 애플리케이션이 실행되는 동안 교환, 추가 또는 제거합니다. 다음과 같은 몇 가지 방법으로 개발 속도를 크게 높일 수 있습니다.
- 전체 다시 로드 중에 손실되는 애플리케이션의 상태를 유지합니다.
- 변경된 사항만 갱신하여 귀중한 개발 시간을 절약하세요.
- 소스 코드에서 CSS/JS를 수정하면 브라우저에서 즉시 업데이트합니다. 이는 브라우저의 개발자 도구에서 직접 스타일을 변경하는 것과 거의 비슷합니다.
출처 : https://webpack.kr/concepts/hot-module-replacement/
Hot Module Replacement | 웹팩
웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.
webpack.kr
// data.json
{
"name":"lee",
"age":12
}
// app.js
import data from './data.json'
function App() {
console.log({data});
}
- 데이터를 import 해
- 와서 사용시 장점은 데이터를 필요할때만 불러서 사용해야하는 동작에 유용하게 작용한다는 장점이 있다.
✅ create-react-app으로 시작하기2
개발할때 https로 실행하고 싶으면?
$ HTTPS=true npm start
window에서
$ (set HTTPS=true && npm start)
build
빌드명령어
$ npm run build
- 빌드하면 정적파일 생성
- 그리고 서버에서는 빌드 폴더 안에 내용들을 정적파일만 서비스하면 된다.
- 서버사이드렌더링으로 동작할수 없다.
$ npx serve -s build
- 로컬에서 정적파일을 서비스하기 위해서 서브패키지를 사용하고
빌드폴더를 대상으로 정적파일을 서비스하는 명령어
- 큰사이즈와 작은사이즈의 이미지를 로드한뒤 빌드했을때
- 큰사이즈의 이미지는 미디어폴더밑에 생성
- 작은사이즈의 이미지는 자바스크립트 파일에 내장된다
- 이유는? http의 요청 횟수를 줄이기 위한 목적
- but http 2.0 부터는 요청 횟수가 많아도 성능에 영향을 크게 받지 않기 때문에 큰 의미는 x
- 좀더 빠르게 이미지를 보여주기 위한 목적
test
$ npm test
- App.test.js를 App.spec.js로 바꾸더라도 test가 인식함
- __tests__ 이름의 폴더를 만들면 폴더 아래의 파일은 모두 test파일이 된다.
eject
- react-scripts를 사용하지 않고 모든 설정 파일을 추출하는 명령어
- cra기반으로 개발환경을 직접 구축하고 싶을 때 사용
- 추출을 하지 않으면 cra의 기능이 추가됐을때 단순히 react-scripts버전만 올리면 되는데 추출을하면 수동으로 설정파일을 수정해야함
polyfill
- padStart()를 사용하고 싶을때 -> 오래된 브라우저는 지원x
- canIuse페이지에서 브라우저별로 지원여부 확인 가능
- IE는 지원되지 않음, IE에서 사용하고 싶다면 폴리필 추가해야한다. - 보통 core-js를 많이 사용한다.
core-js(-pure)/es|stable|features/string/pad-start
경로를 복사해서 index.js에 추가해준다
import 'core-js/features/string/pad-start'이렇게 설치해서 코드에서 마음놓고 사용하면 된다. - 원래는 npm run core-js 설치해서 사용하지만
- cra에서는 기본적으로 core-js가 내장되어 있기 때문에 필요한 부분만import해주면 된다.
환경변수
- 개발, 테스트, 배포 환경별로 다른 값을 적용할때 유용하다.
- 전달된 환경변수는 코드에서 process.env.{변수이름} 과 같이 사용한다.
- cra에서는 기본적으로 process.env.NODE_ENV라는 환경변수를 갖고 있다.
- process.env.NODE_ENV는
- npm start -> development
- npm test -> test
- npm run build 로 실행하면 production 이라는 값을 가지고 있는다. - 환경변수를 커맨드라인에서도 실행할 수 있다.
- REACT_APP_*으로 항상 시작
- process.env.REACT_APP_API_URL
// 윈도우버전
$ set "REACT_APP_API_URL=api.myapp.com" && npm start
console.log('process.env.REACT_APP_API_URL',process.env.REACT_APP_API_URL);
콘솔로 출력해본 결과 변수의 값이 출력된다. (but 난 undefined가 찍힌다..?)
- 환경변수가 많아지면 .env파일로 관리하는게 좋다.
- 개발용, 배포용 따로 만들어서 콘솔로 찍어본다.
// 개발용
REACT_APP_API_URL=api.myapp.com
REACT_APP_TEMP1=temp_dev1
// 배포용
REACT_APP_API_URL=api-prod.myapp.com
REACT_APP_TEMP1=temp_prod1
console.log('process.env.REACT_APP_temp1',process.env.REACT_APP_API_TEMP1);
서버로 연결해서 확인시 배포했을때 배포용 정의가 출력되고 개발모드시에는 개발했을때의 결과가 출력된다. (이부분도 undefined 출력..)
- 배포용 콘솔 결과창
1. process.env.NODE_ENV production
2. process.env.REACT_APP_API_URL api-prod.myapp.com
3. process.env.REACT_APP_temp1 undefined
✅ CSS 작성 방법 결정하기
일반적인 방법
- 일반적인 css 파일로 작성할때는 이름이 충돌할 수 있다는 문제점이 있다.
- 빌드해서 css파일을 확인해보면 이름 같아서 겹치는 것을 확인할 수 있음, 마지막 선언된 css 속성만 적용돼서 문제가 생겼음
css module
- Box.module.css 처럼 css 파일의 모듈이름을 .module.css으로 작성해주고
- import할떄는 import style from './Button.module.css 로 받아서
- 객체 형식이기 떄문에 Style.big ,Style.small클래스명을 그 속성 이름으로 해주면 된다.
- 콘솔에 출력해보면 객체 형태로 출력된다.
- 객체 속성의 값을 보면 해시값이 붙어있다.
- 이 해시값 덕분에 각 클래스명은 고유한 이름을 부여받을 수 있다.
- 때문에 이름 충돌 문제가 없다.
클래스네임 입력하는게 다소 번거로울 경우 간편하게 하는 방법
classNames 패키지 이용
$ npm install classNames
사용법 classnames를 import
import cn from 'classnames'
<button className={cn(style.Button,style.big)}>큰 버튼</button>
css Sass
- Sass문법에 있는 변수나 믹스인을 이용하면 스타일 코드 재사용할 수 있음
- cra에서 Sass를 사용을 위한 패키지 설치 - node-sass
$ npm install node-sass
- css 파일 확장명은 scss
css-in-js
- css 코드를 자바스크립트 파일 안에서 작성하는 방식
- css 코드도 얼마든지 재사용이 가능한 구조로 관리할 수 있음
- 동적으로 css 코드를 작성하기도 쉽다.
- styled-components 라이브러리 사용
$ npm install styled-components
import styled from 'styled-components';
const BoxCommon = styled.div`
height : 50px;
background-color:#ffff;
`;
const Big = styled(boxCommon) `
width:200px;
`;
- 값을 매개변수로 받아와서 실행하는 함수가 있다라고 이해하면 된다.
- div로 이루어진 컴포넌트를 생성
- 이를 확장해서 또 다른 컴포넌트를 만들 수 있다.
const BoxCommon = styled.button`
width:${props => {props.isBig ? 100 : 50 }}px;
`;
위처럼 동적으로 코드를 작성할 수도 있다.
✅ 단일 페이지 애플리케이션(SPA) 만들기
- 전통적인 방식 (MPA)
- 단일 페이지 애플리케이션(SPA)
- 클라이언트가 초기 요청을 보내고 서버가 html을 보내주는 방식은 전통적인 방식과 똑같다.
- 그 이후에 페이지 전환 요청이 있으면 서버로 항상 요청하는 것이 아니라 필요할때만 데이터를 요청해서 받아오는 방식
- 페이지 전환은 자체적으로 라우팅 처리를 할 수 있다.
SPA가 가능하기 위한 조건
- 자바스크립트에서 브라우저로 페이지 전환 요청을 보낼 수 있어야 한다.
- 이때 브라우저는 서버로 요청을 보내지 않아야 한다. - 브라우저에서 뒤로가기와 같은 사용자의 페이지 전환 요청을 자바스크립트에서 처리할 수 있어야한다.
- 이때도 브라우저는 서버로 요청을 보내지 않아야 한다.
페이지 전환 이벤트
- 페이지 전환 이벤트는 브라우저와 자바스크립트 양쪽에서 발생할 수가 있는데, 어떤 경우든 서버로 요청은 하지 않는다.
- 사용자가 브라우저 UI를 통해서 페이지 전환 요청을 하면 브라우저는 자바스크립트한테 알려줘야하고 자바스크립트가 페이지 전환을 하고싶을때는 브라우저에게 알려줘야한다.
위 조건을 만족시켜주는 브라우저 API
- pushState, replaceState함수
- js가 페이지 전환을 하고싶을때 브라우저에게 페이지 전환 이벤트를 알려주는 방법으로 이 함수를 사용한다. - popState 이벤트
- 반대로 사용자가 브라우저 UI를 통해서 페이지 전환하려고할때 브라우저는 js로 popState 이벤트를 통해 알려준다.
SPA 방식으로 페이지 만들어보기
import React, { useEffect } from 'react';
import ReactDOM from 'react-dom';
function App() {
useEffect(()=>{
window.onpopstate = function (event) {
console.log(`location: ${document.location},state: ${event.state}`);
}
},[]);
- 브라우저에서 페이지 전환 요청이 발생했을때는 자바스크립트가 알기 위해서 onpopstate 이벤트 핸들러를 등록하고 있다.
- useEffect는 이벤트 핸들러를 등록하거나 api를 호출하는 등의 부수효과를 발생시킬때 사용하는 리액트 함수
- pushState 함수는 브라우저에게 알려주는 것
return (
<div>
<button onClick={() => window.history.pushState('v1','','/page1')}>
page1
</button>
<button onClick={() => window.history.pushState('v2','','/page2')}>
page2
</button>
</div>
)
}
- pushState의 첫번째 매개변수 v1은 데이터를 의미
- onpopstate에서 event.state가 있는데 onpopstate에서 넘겨주는 그 값이 첫번째 매개변수의 값이다.
- 세번째 매개변수는 url 클릭하면 주소창에 설정한 값이 보인다.
react-router-dom을 이용해서 구현
- react-router-dom은 여러가지 편의 기능을 제공해준다.
- 컴포넌트를 다양한 조건으로 렌더링할때 라이브러리에서 제공해주는 기능을 활용하면 좋다.
- 라이브러리에서는 현재 상태 정보 관리를 자동으로 해준다.
- 코드스플리팅(분할)이라는 기능도 제공한다.
- 쉽게 페이지 단위로 코드 분할이 가능하다.
import {Route, Link} from 'react-router-dom';
export default function Rooms({match}) {
return (
<div>
<h2>여기는 방을 소개하는 페이지입니다.</h2>
<Link to={`${match.url}/blueRoom`}>파란방입니다.</Link>
// ...생략
</div>
)
}
function Room({match}) {
return <h2>{`${match.params.roomId} 방을 선택하셨습니다.`}</h2>
}
- match란?
- 라우터 컴포넌트로 렌더링을 하면 해당 컴포넌트의 속성값으로 match라는 속성값을 넣어준다.
- match에는 url이라는 속성이 있다. 의미는 Rooms컴포넌트가 렌더링 됐을 당시에 match됐던 그 url의 일부분
- match.url은 rooms로 되어있다고 생각하면 된다.
🔍 강의 출처
실전 리액트 프로그래밍🧷 관련 링크
리액트 프로젝트 시작하기
페이스북에서 개발하고 관리하는 UI 라이브러리리액트는 UI 기능만 제공 ( 앵귤러가 웹앱 개발에 필요한 다수의 기능을 제공하는 것과는 달리)따라서 전역상태관리, 라우팅, 빌드 시스템 등을 각
velog.io
'React > 실전 리엑트 프로그래밍' 카테고리의 다른 글
[React.js]리액트의 가상돔, 리액트 훅 기초 (0) | 2023.04.12 |
---|---|
[React.js]리액트의 상탯값, 속성값, 반환값 (0) | 2023.04.12 |
중요하지만 헷갈리는 리액트 개념 이해하기 2 (0) | 2023.04.12 |
중요하지만 헷갈리는 리액트 개념 이해하기 (0) | 2023.04.10 |
실전 리액트 프로그래밍 section 1. 리액트 프로젝트 시작하기 (0) | 2023.04.10 |