React JS
2022. 4. 15. 10:30ㆍStudy/JavaScript
React JS
- 공식사이트 https://reactjs.org/
- 한국어 지원 사이트 https://ko.reactjs.org/
Facebook에서 개발한 자바스크립트 라이브러리(프레임워크가 아니다)이다.
SPA(Single Page Application)이며 가상 DOM(Virtual DOM)을 활용한다.
다른 프레임워크나 라이브러리와 혼용이 가능하다
*장점
#Component
컴포넌트란 UI를 구성하는 개별적인 view 단위이다.
전체의 앱은 각 컴포넌트를 조립해서 만들어진다.
모듈화를 통해 유지, 보수가 용이하다는 점이 있다.
본인에게는 컴포넌트가 모듈화의 가이드라인을 제시해주는 것처럼 느껴진다.
#JSX
React에서 새로 도입된 자바스크립트 문법이고 React에서만 사용된다.
JSX 문법을 사용하지 않고도 React 개발이 가능하며,
또한 브라우저에게 이해시키기 위해서는 초기 Webpack 설정이 필수(create-react-app을 사용하면 자동으로 추가되지만)이다.
그럼에도 JSX를 사용하는 중요한 이유중 하나는 코드의 직관성이다.
HTML과 JavaScript를 분리하여 개발하는 것이 기존의 개발 방법이었다.
그래서 한쪽의 코드만 봤을 때 이 코드가 정확히 어떤 동작을 하는 것인지 쉽게 알 수 없었다.
이에 유저에게 보여주고 싶은 view에 개발자가 직관적으로 도달할 수 있도록,
마치 HTML과 JavaScript가 합쳐진 것처럼 보이는 JSX가 도입되었다.
https://ko.reactjs.org/docs/introducing-jsx.html
#Virtual DOM
DOM은 브라우저가 화면을 그리기위한 정보를 담고있는 문서 객체이다.
JQuery처럼 실제 DOM을 변경할 경우, 변경할 부분이 일부분이더라도 DOM 전체를 다시 렌더링해야하고, 이는 성능 저하로 직결된다는 단점이 있다.
React는 렌더링 시 Virtual DOM, 즉 가상 DOM을 먼저 만든다.
그 후 실제 DOM과 비교를 하여 변경이 있는 부분(하위 컴포넌트)만 대체를 하기 때문에 리소스 낭비를 줄일 수 있다.
라이브러리를 통해 React에서도 JQuery를 사용할 수 있지만 이는 추천되지 않는 방법이다.
#단반향 데이터 바인딩
React 내에서의 데이터의 흐름은 부모(Parent)에서 자식(Child)으로 단방향적이다.
그렇기 때문에 디버깅이 용이하며, 다른 라이브러리에 비해 안전성이 높다.
다만, 전역에서 접근해야하는 데이터가 존재할 경우(로그인 여부 등...)가 있고, 이는 Redux를 통해 관리를 하는 방법도 존재한다.
#활발한 커뮤니티
모든 기술이 그렇듯 커뮤니티가 얼마나 크고 활발한지가 해당 기술을 선택하는 척도 중 하나다.
여러 자바스크립트 라이브러리와 프레임워크가 있겠지만 그 중에서도 React가 제일 높은 시장 점유율과 선호도를 갖고 있다.
그렇기 때문에 다양한 라이브러리 사용이 가능해진다.
#React Native
리액트 네이티브를 활용한 앱 개발이 가능하다.
앱의 운영 환경(Android, iOS) 과는 상관없이 작동하는 앱을 만들 수 있다.
본인은 아직 시도해보지 않았지만 몇가지 태그와 속성을 제외하면 React JS와 동일하다고 알고있다.
01. CLI 설치하기
1. node js 설치 (최신버전)
- 안정화 버전 다운로드 14.15.1 LTS
2. visual studio code 설치
- https://code.visualstudio.com/
3. 리액트 설치하기
https://www.youtube.com/watch?v=nahwuaXmgt8
3-1. 명령프롬프트 열기, 버전확인
node -v (버전확인, 최신버전이 좋다)
npm -v (npm 버전확인)
3-2. 설치하기
my-app 은 생성 될 폴더 이름이다.
생성될 폴더 > npx create-react-app my-app (실제 프로젝트 폴더 생성 및 세팅, my-app이 폴더이름)
Ok to preceed? (y) => y
4. 페이지 확인하기
설치한 폴더로 꼭!!!! 경로 변경을 해준 후 실행
리액트 설치 폴더 > npm start
5. 실행 종료 방법
ctrl + c => 실행을 끈다
02. 세팅된 파일 설명
31번째 줄 <div id="root"></div>가 있다.
3번째 줄 import './index.css';가 연결되어 있다.
4번째 줄 import App from './App'; .js가 생략되어 있다.
7번째 줄 => ReactDom과 render를 사용해서 -> #root 에 App 컴포넌트를 렌더하라는 내용
(기본 파일들을 import한다)
작업이 이뤄질 메인 컴포넌트
2번째 줄 import '/App.css';
<div className="App"> 은 꼭 있어야 한다.
HTML은 어디에.....?
React JS는 html태그를 스크립트 안에 포함하고 있다.
이 문법을 JSX 스크립트라고 한다. (리액트에서만 사용한다)
CSS파일은 분리되어 있다.
index.css => reset, common, 공통 CSS
App.css => app 컴포넌트와 연결된 CSS
03-0. React 기본문법 2가지
리액트 기본 문법은 2가지가 있다.
신 모델인 function type과 구 모델인 class type이 있다.
https://www.youtube.com/playlist?list=PLuHgQVnccGMCEfBwnNGsJCQDiqSWI-edj
class type 컴포넌트 기본 문법
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render(){
return (
<div className="App">
// JSX
</div>
);
}
}
export default App;
function type 컴포넌트 기본 문법 (NEW)
function 방식에서는 일반 함수를 컴포넌트로 쓰기 때문에 페이지 상단에 컴포넌트 import문이 필요없다.
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
</div>
);
}
export default App;
기초 function
기본 세팅 변경
src/App.js
import './App.css';
function App() {
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
</div>
</div>
);
}
export default App;
src/App.css
.black-nav {
background : black;
width : 100%;
display : flex;
color : white;
padding : 20px;
font-weight : 600;
font-size : 20px;
}
src/index.css
*{margin:0; padding:0;}
html{font-size: 16px;}
body{color:#333; font-family: sans-serif; line-height: 1;}
a{color:inherit; text-decoration: none;}
ul, ol{list-style: none;}
img{border:0 none; vertical-align: top;}
JSX에서 데이터바인딩하기 { }
src/App.js
import './App.css';
function App() {
var data = 'nav'; // 일반변수
var text = '안녕하세요';
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
<div className={data}>{text}</div>
</div>
</div>
);
}
export default App;
HTML에 스타일을 직접 넣고 싶으면
<div style={ {color : 'blue', fontSize : '30px'} }> 글씨 </div>
state
리액트에서도 변수 자유롭게 만들고 변수에 데이터 아무렇게나 저장해서 쓰실 수 있는데
데이터바인딩과 관련된 중요한 데이터를 저장할 땐 변수 대신 state를 만들어 씁니다.
src/App.js
function App(){
let posts = '강남 고기 맛집';
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
</div>
<div className="list">
<h3>{ posts }</h3>
<p>2월 17일 발행</p>
<hr/>
</div>
</div>
)
}
src/App.css
.list {
margin-top : 30px;
text-align : left;
padding-left : 20px;
padding-right : 20px;
}
state를 만들어서 데이터를 저장해봅시다
useState()라는 함수는 state를 하나 만들어주는 함수입니다.
이걸 각각 a와 b라는 변수명으로 ES6 destructuring 문법을 이용해 저장해서 쓰시면 됩니다.
a라는 변수엔 실제 저장할 데이터가 들어있고
b라는 변수엔 저장할 데이터를 변경시킬 함수가 들어있습니다.
ex) let [변수1, 변수2] = useState('저장할 데이터'); // 변수1 = '저장할 데이터'
src/App.js
import React, { useState } from 'react'; // 를 꼭 추가해야 한다.
import React, { useState } from 'react'; // 꼭 추가해야 한다. ☆★
import './App.css'
function App(){
let [a, b] = useState('남자 코트 추천'); // a = '남자 코트 추천'
let posts = '강남 고기 맛집';
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
</div>
<div className="list">
<h2>{ posts }</h2>
<h3>{ a }</h3>
<p>2월 17일 발행</p>
<hr/>
</div>
</div>
)
}
export default App;
state 데이터도 똑같이 변수처럼 데이터바인딩 가능합니다
src/App.js
import React, { useState } from 'react'; // 꼭 추가해야 한다. ☆★
import './App.css'
function App(){
let [글제목, 글제목변경] = useState('남자 코트 추천');
let posts = '강남 고기 맛집';
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
</div>
<div className="list">
<h2>{ posts }</h2>
<h3>{ 글제목 }</h3>
<p>2월 17일 발행</p>
<hr/>
</div>
</div>
)
}
export default App;
state에는 Array, Object 아무거나 다 넣을 수 있습니다
src/App.js
import React, { useState } from 'react'; // 꼭 추가해야 한다. ☆★
import './App.css'
function App(){
let [글제목, 글제목변경] = useState( ['남자 코트 추천', '여자 코트 추천'] );
let [글내용, 글내용변경] = useState( { a:'남자 코트 추천 내용', b:'여자 코트 추천 내용'} );
let [글내용2, 글내용변경2] = useState( [
{ a:'남자 코트 추천 내용0-2', b:'여자 코트 추천 내용0-2'},
{ a:'남자 코트 추천 내용1-2', b:'여자 코트 추천 내용1-2'}
] );
return (
<div className="App">
<div className="black-nav">
<div>개발 blog</div>
</div>
<div className="list">
<h3>{ 글제목[0] }</h3>
<p>2월 17일 발행</p>
<p>{ 글내용.a }</p>
<p>{ 글내용2[0].a }</p>
<p>{ 글내용2[0].b }</p>
<hr/>
</div>
<div className="list">
<h3>{ 글제목[1] }</h3>
<p>2월 17일 발행</p>
<p>{ 글내용.b }</p>
<p>{ 글내용2[1].a }</p>
<p>{ 글내용2[1].b }</p>
<hr/>
</div>
</div>
)
}
export default App;
변수 말고 state에 데이터 저장해서 쓰는 이유
- 힘들게 state를 만들어 써야하는 이유는 이겁니다.
"변수가 변경될 때 자동으로 관련된 HTML을 재렌더링되게 만들고 싶으면"
그럴 때 변수 말고 state에 저장해서 데이터바인딩 하셔야합니다.
- 리액트는 state가 수정이 일어나면 state가 포함된 HTML을 자동으로 재렌더링 해줍니다.
- 웹앱을 만들고 싶으면 좋은말 할 때 state에 중요데이터들을 저장해 사용하시길 바랍니다.
(일반 변수는 변경이 발생해도 자동으로 재렌더링 해주지 않습니다.)
- 바뀌지 않는 데이터들은 state로 굳이 저장할 필요 없습니다.
state의 가장 큰 장점은 state가 변경될 때마다 자동으로 state와 관련된 HTML이 재렌더링이 된다는 것인데
로고명은 아예 바뀔 일이 없으니 의미가 없겠죠.
state는 상품명, 글제목, 가격 이런것 처럼 자주 변하는 데이터들을 저장하시는게 좋은 관습입니다.
버튼의 기능을 만들어봅시다-이벤트
1. Click이 대문자인거
2. {} 중괄호 사용하는거
3. 그냥 코드가 아니라 함수를 적는거
ex) 3가지 방식
<div onClick={ showModal }> (showModal은 어디 다른데 만들어둔 함수 이름)
<div onClick={ function(){ 실행할 코드 } }> // 익명함수
<div onClick={ () => { 실행할 코드 } }> // 익명, 화살표 함수
src/App.js
import React, { useState } from 'react'; // 꼭 추가해야 한다. ☆★
import './App.css'
function App(){
let [글제목, 글제목변경] = useState( ['남자 코트 추천', '강남 우동 맛집'] );
let [ 따봉, 따봉변경 ] = useState(0);
return (
<div>
<h3> { 글제목[0] } <span onClick={ ()=>{ 따봉변경(따봉 + 1) } } >클릭</span> { 따봉 }</h3>
</div>
)
}
export default App;
Class방식
ex1) App.js 파일 수정하기
src/App.js
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render(){
return (
<div className="App">
안녕하세요!
</div>
);
}
}
export default App;
*주의사항
return (); 안에 JSX는 오직 하나의 부모 태그만 존재해야한다
return (
<div className="App">
안녕하세요!
</div>
);
ex2) css코딩하는 방법
index.js 파일의 상단에
import './index.css'; //코드를 볼수 있다
index.css 파일 변경
body{background-color: aquamarine; font-size: 30px; font-weight: bold;}
index.js 파일의 상단에
import App from './App'; // ./App.js 파일을 import
App.js 파일의 상단에
import './App.css'; //코드를 볼수 있다
App.js 파일에서 만들어진 Component 의 디자인을
수정할 수 있게 해주는 css파일이다 (./App.css)
이파일을 수정해서 스타일링을 할 수 있다
리액트에선 HTML대신 JSX 써야함 (JSX 사용법)
- 해당 요소(태그)에 class="클래스명" 을 사용할 수 없다.
className="클래스명" 으로 사용해야 한다 (class라는 문법과 충돌하기 때문)
src/App.js
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render(){
return (
<div className="App">
<div className="black-nav">
<div>개발 BLOG</div>
</div>
<h3>블로그글</h3>
</div>
);
}
}
export default App;
src/App.css
.black-nav{
background: black;
width:100%;
color:white;
padding: 20px;
font-weight: bold;
font-size: 20px;
}
.list {
margin-top : 30px;
text-align : left;
padding-left : 20px;
padding-right : 20px;
}
- React에서 데이터 바인딩(서버 등에서 데이터를 가지고 와써 html 화 시키는 방법) 쉽게하는 방법
{변수명,함수 등}
- JXS 에서 style 속성을 집어넣을 때
<div style="font-size:20px; color:red">스타일 변경</div> -> 에러
-> style={object 자료형으로 만든 스타일}
<div style={ {fontSize:'20px' , color:'red'} }>스타일 변경</div>
src/App.js
import React, { Component } from 'react';
import './App.css';
import logo from './logo.svg';
class App extends Component {
render(){
let posts = '강남 고기 맛집';
let cname = 'kim';
let cstyle = {fontSize:'30px' , color:'blue'};
function num(){
return 100;
}
return (
<div className="App">
<div className="black-nav">
<div>개발 BLOG</div>
</div>
<h3>{ posts }</h3>
<h3>{ num()+100 }</h3>
<img src={logo} alt="로고입니다." />
<p className={cname}>단락요소입니다</p>
<div style={ {fontSize:'20px' , color:'red'} }>스타일 변경</div>
<div style={ cstyle }>스타일 변경2</div>
</div>
);
}
}
export default App;
* 터미널에 뜨는 warning eslint(경고메시지)를 안보이게 하는 방법
App.js 상단에
/* eslint-disable */ -> 주석을 추가한다
ex3) sample.html 생성
public 폴더에 임의의 (sample.html) 파일을 생성하고, html:5 템플릿을 생성한다.
public/sample.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<header>
<h1>WEB</h1>
world wide web!
</header>
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
<article>
<h2>HTML</h2>
HTML is HyperText Markup Language.
</article>
</body>
</html>
http://localhost:3000/sample.html 을 입력하면 페이지가 실행된다
ex4) 컴포넌트 만들기 ★★★★★
- 반복 출현하는 HTML 코드를 관리
자주 변경되는 html UI들
다른 페이지를 만들 때 컴포넌트 용이
- App.js 파일에 컴포넌트 만들기
- Subject라는 컴포넌트 만들기 (주의 : 컴포넌트 이름의 첫글자는 반드시 대문자로 시작)
src/App.js
http://localhost:3000 //에서 확인하면 <Subject></Subject> 컴포넌트가 처리되는걸 확인할 수 있다
import React, { Component } from 'react';
import './App.css';
class Subject extends Component {
render(){
return (
<header>
<h1>WEB</h1>
world wide web!
</header>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<Subject>Subject 컴포넌트</Subject>
</div>
);
}
}
export default App;
ex4-1) <nav>,<article>태그 부분도 Gnb,Content 라는 이름의 컴포넌트로 만들기
src/App.js
import React, { Component } from 'react';
import './App.css';
class HeaderArea extends Component {
render(){
return (
<header>
<h1>WEB</h1>
world wide web!
</header>
);
}
}
class Gnb extends Component {
render(){
return (
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
);
}
}
class Content extends Component {
render(){
return (
<article>
<h2>HTML</h2>
HTML is HyperText Markup Language.
</article>
);
}
}
class Footer extends Component {
render(){
return (
<footer>
Copyright ©
</footer>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<HeaderArea>Subject 컴포넌트</HeaderArea>
<Gnb />
<Content />
<Footer />
</div>
);
}
}
export default App;
ex5) props (컴퍼넌트의 속성을 변경할 수 있다)
<HeaderArea props='값'></HeaderArea>
https://reactjs.org/docs/components-and-props.html
src/App.js
import React, { Component } from 'react';
import './App.css';
class Subject extends Component {
render(){
return (
<header>
{/* title, sub 이란 속성이 만들어 짐 */}
<h1>{this.props.title}</h1>
<p>{this.props.sub}</p>
</header>
);
}
}
class Gnb extends Component {
render(){
return (
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
);
}
}
class Content extends Component {
render(){
return (
<article>
{/* title, desc 이란 속성이 만들어 짐 */}
<h2>{this.props.title}</h2>
<p>{this.props.desc}</p>
</article>
);
}
}
class Footer extends Component {
render(){
return (
<footer>
Copyright ©
</footer>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<Subject title="WEB" sub="world wide web!"></Subject>
<Subject title="React" sub="for ui!"></Subject>
<Gnb></Gnb>
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
React Developer Tools (크롬 확장 프로그램 추가)
- 개발자 도구에 탭메뉴에 Component 메뉴가 추가된다.
ex6) Component 각각의 파일로 분리하기
- src 폴더에 components 폴더를 만든다
- components 폴더에 Gnb.js 파일을 만든다
- App.js 파일에 있는 Gnb 콤퍼넌트를 Gnb.js파일에 import 한다
src/components/Subject.js
import React, { Component } from 'react';
class Subject extends Component {
render(){
return (
<header>
{/* title, sub 이란 속성이 만들어 짐 */}
<h1>{this.props.title}</h1>
<p>{this.props.sub}</p>
</header>
);
}
}
export default Subject;
src/components/Gnb.js
import React, { Component } from 'react';
class Gnb extends Component {
render(){
return (
<nav>
<ul>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ul>
</nav>
);
}
}
export default Gnb;
src/components/Content.js
import React, { Component } from 'react';
class Content extends Component {
render(){
return (
<article>
{/* title, desc 이란 속성이 만들어 짐 */}
<h2>{this.props.title}</h2>
<p>{this.props.desc}</p>
</article>
);
}
}
export default Content;
src/components/Footer.js
import React, { Component } from 'react';
class Footer extends Component {
render(){
return (
<footer>
Copyright ©
</footer>
);
}
}
export default Footer;
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
render(){
return (
<div className="App">
<Subject title="WEB" sub="world wide web!"></Subject>
<Subject title="React" sub="for ui!"></Subject>
<Gnb></Gnb>
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
<Content title="JavaScript" desc="JavaScript is......"></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
ex7) state ★★★★★
state변수(배열, 객체, 객체배열) => 값이 변경되면 자동으로 랜더링 발생된다.
1. Props -> 사용자는 해당 컴포넌트를 조작할 수 있다 (속성과 유사)
<Component props_name="props_value">
- State -> Props 에 따라서 컴포넌트를 실제로 구현한 내부의 정보
2. 함수형 컴포넌트 Hook - useState()를 사용할 수 있다
import React, { useState } from "react"; //상단 추가 , class방식일때는 생략한다
state를 사용하능 방식은 2가지가 있다. 클래스방식 / 함수방식
클래스방식 src/App.js
컴포넌트 안에 constructor(props){ } 를 추가한다.
위치에 주의한다~
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
subject:{title:'WEB' , sub:'world wide web!'}
}
}
render(){
return (
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject>
<Gnb></Gnb>
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
<Content title="JavaScript" desc="JavaScript is......"></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
ex8) key
반복문을 사용해서 태그를 만들어 사용할 때 꼭!!!!! key 속성 을 사용해야 한다.
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
subject:{title:'WEB' , sub:'world wide web!'},
contents:[
{id:1, title:'HTML', desc:'설명글1'},
{id:2, title:'CSS', desc:'설명글2'},
{id:3, title:'JavaScript', desc:'설명글3'}
]
}
}
render(){
return (
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject>
{/* this.state contents 를 data에 담아서 Gnb 컴포넌트에 보낸다. */}
<Gnb data={this.state.contents}></Gnb>
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
src/components/Gnb.js
import React, { Component } from 'react';
class Gnb extends Component {
render(){
var lists =[];
// data에 props.데이터를 받아와 쓰겠다. (App.js 로부터 받아온 contents객체배열)
var data = this.props.data;
var i=0;
while(i<data.length){ // 0 1 2
lists.push(<li key={data[i].id}>
<a href={data[i].id+".html"} title={data[i].desc}>
{data[i].title}
</a>
</li>);
i+=1;
}
return (
<nav>
<ul>
{lists}
</ul>
</nav>
);
}
}
export default Gnb;
ex9) 이벤트 state props 그리고 render 함수
* state, props의 값이 바뀌면 그 값을 가지고 있는 render()함수가 다시 호출되면서
render()함수 하위에 있는 컴포넌트들이 새로 다시 호출된다. (새로 화면이 새로 다시 그려지게된다)
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'welcome',
welcome:{title:'welcome' , desc:'hello React!'},
subject:{title:'WEB' , sub:'world wide web!'},
contents:[
{id:1, title:'HTML', desc:'설명글1'},
{id:2, title:'CSS', desc:'설명글2'},
{id:3, title:'JavaScript', desc:'설명글3'}
]
}
}
render(){
var _title, _desc=null; // 일반변ㅅ
if(this.state.mode === 'welcome'){
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
}else if(this.state.mode === 'read'){
_title = this.state.contents[0].title;
_desc = this.state.contents[0].desc;
}
return (
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject>
{/* this.state contents 를 data에 담아서 Gnb 컴포넌트에 보낸다. */}
<Gnb data={this.state.contents}></Gnb>
<Content title={_title} desc={_desc}></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
- mode:'welcome' 부분을 -> mode:'read' 로 수정해 본다.
ex9-1) 이벤트 설치 ★★★★★
* onClick={} //React는 이벤트 핸들러 연결시 꼭 카멜케이스 방법을 사용해야 한다
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
// import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'welcome',
welcome:{title:'welcome' , desc:'hello React!'},
subject:{title:'WEB' , sub:'world wide web!'},
contents:[
{id:1, title:'HTML', desc:'설명글1'},
{id:2, title:'CSS', desc:'설명글2'},
{id:3, title:'JavaScript', desc:'설명글3'}
]
}
}
render(){
var _title, _desc=null; // 일반변ㅅ
if(this.state.mode === 'welcome'){
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
}else if(this.state.mode === 'read'){
_title = this.state.contents[0].title;
_desc = this.state.contents[0].desc;
}
return (
<div className="App">
{/* <Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject> */}
<header>
<h1>
<a href="#" onClick={
function(e){
e.preventDefault();
console.log('clicked h1');
}}>
{this.state.subject.title}
</a>
</h1>
<p>{this.state.subject.sub}</p>
</header>
{/* this.state contents 를 data에 담아서 Gnb 컴포넌트에 보낸다. */}
<Gnb data={this.state.contents}></Gnb>
<Content title={_title} desc={_desc}></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
ex9-2) 이벤트에서 state 변경하기
* bind()함수 -> App에서 만들어진 state를 해당 이벤트 함수안에서 this로 사용하기 위한 함수
* setState()함수 -> 이벤트 함수에서 state 값을 변경할 때 객체형태로 변경해야 한다
onClick={function(e){
e.preventDefault();
this.setState({
mode:'read'
});
}.bind(this)} //추가하기 이벤트 안에서는 this를 인식하지 못한다.
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
// import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'welcome',
welcome:{title:'welcome' , desc:'hello React!'},
subject:{title:'WEB' , sub:'world wide web!'},
contents:[
{id:1, title:'HTML', desc:'설명글1'},
{id:2, title:'CSS', desc:'설명글2'},
{id:3, title:'JavaScript', desc:'설명글3'}
]
}
}
render(){
var _title, _desc=null; // 일반변ㅅ
if(this.state.mode === 'welcome'){
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
}else if(this.state.mode === 'read'){
_title = this.state.contents[0].title;
_desc = this.state.contents[0].desc;
}
return (
<div className="App">
{/* <Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject> */}
<header>
<h1>
<a href="#" onClick={
function(e){
e.preventDefault();
//this.state.mode = 'read'; 에러가 발생한다 직접 값을 수정할 수 없다
this.setState({
mode:'read'
});
}.bind(this)}>
{this.state.subject.title}
</a>
</h1>
<p>{this.state.subject.sub}</p>
</header>
{/* this.state contents 를 data에 담아서 Gnb 컴포넌트에 보낸다. */}
<Gnb data={this.state.contents}></Gnb>
<Content title={_title} desc={_desc}></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
ex10) 컴포넌트 이벤트 만들기
Redux를 알아보자~
src/App.js
import React, { Component } from 'react';
import Gnb from "./components/Gnb";
import Subject from "./components/Subject";
import Content from "./components/Content";
import Footer from "./components/Footer";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'welcome',
welcome:{title:'welcome' , desc:'hello React!'},
subject:{title:'WEB' , sub:'world wide web!'},
contents:[
{id:1, title:'HTML', desc:'설명글1'},
{id:2, title:'CSS', desc:'설명글2'},
{id:3, title:'JavaScript', desc:'설명글3'}
]
}
}
render(){
var _title, _desc=null; // 일반변수
if(this.state.mode === 'welcome'){
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
}else if(this.state.mode === 'read'){
_title = this.state.contents[0].title;
_desc = this.state.contents[0].desc;
}
return (
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function(){
this.setState({
mode:'read'
});
}.bind(this)}
>
</Subject>
{/* this.state contents 를 data에 담아서 Gnb 컴포넌트에 보낸다. */}
<Gnb data={this.state.contents}></Gnb>
<Content title={_title} desc={_desc}></Content>
<Footer></Footer>
</div>
);
}
}
export default App;
src/component/Subject.js
import React, { Component } from 'react';
class Subject extends Component {
render(){
return (
<header>
<h1>
<a href="#" onClick={function(e){
e.preventDefault();
this.props.onChangePage();
}.bind(this)}>
{this.props.title}</a>
</h1>
{this.props.sub}
</header>
);
}
}
export default Subject;
ex10-1) Gnb 영역의 리스트 클릭시 Content값 변경하기
src/App.js
src/component/Gnb.js
Function 방식
function 방식에서는 일반 함수를 컴포넌트로 쓰기 때문에 페이지 상단에 컴포넌트 import문이 필요없다.
[function] src/App.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
React Hello!
</div>
);
}
export default App;
{이벤트 핸들링}
<button onClick={함수}>Submit</button>
onClick -> 이벤트 핸들러는 꼭!! 카멜케이스 방식을 사용한다.
ex1) App.js 이벤트 호출하기
[Function] src/App.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
<button onClick={()=>alert('hello')}>Submit</button>
</div>
);
}
export default App;
ex1-1) 이벤트를 사용한 함수호출
[Function] src/App.js
import React from 'react';
import './App.css';
function App() {
const onSubmit = () => {
alert('전송 되었습니다');
};
return (
<div className="App">
<button onClick={onSubmit}>Submit</button>
</div>
);
}
export default App;
ex1-2) onKeyup 이벤트 사용
주의! - JSX내에서 함수를 부를 때에는 ( ) 괄호 사용 XX
import React from 'react';
import './App.css';
function App() {
const onSubmit = () => {
alert('submit 되었습니다');
};
const Keyup = (event) => {
if(event.keyCode === 13){ // 13은 enter 값
onSubmit();
}
//console.log('key up!');
};
return (
<div className="App">
<input type='text' onKeyUp={Keyup}/>
<button onClick={onSubmit}>Submit</button>
</div>
);
}
export default App;
{리액트 훅(Hook)스 useState}
ex2) 일반 변수 사용
[Function] src/App.js
import React from 'react';
import './App.css';
function App() {
const onSubmit = () => {
alert('submit 되었습니다');
};
const Keyup = (event) => {
if(event.keyCode === 13){ //13은 enter 값
onSubmit();
}
//console.log('key up!');
};
let text = 'Hello HTML';
const updateText = () => {
text = 'Hello React';
console.log(text);
//document.getElementById('text').innerHTML = text; //이 코드를 사용해야지만 처리가 된다
}
return (
<div className="App">
<input type='text' onKeyUp={Keyup}/>
<button onClick={onSubmit}>Submit</button>
<br/><br/>
<span id="text">{text}</span>
<button onClick={ updateText }>Update</button>
</div>
);
}
export default App;
ex2-1) useState 사용 ★★★★★
[Function] src/App.js
useState를 사용하려면 페이지 상단에 { useState } 가 추가되어야 한다.
변수 선언 시 useState() 사용
ex) let [text, setText] = useState('저장할 데이터'); // text = '저장할 데이터'
// text => '저장할 데이터' => 배열, 객체, 객체배열 가능
// setText('변경될 값') => 함수, text 변수 값을 변경할 수 있다.
import React, { useState } from 'react'; //추가
import './App.css';
function App() {
const [text, setText] = useState('Hello HTML'); // 추가
// text => '저장할 데이터' => 배열, 객체, 객체배열 가능
// setText('변경될 값') => 함수, text 변수 값을 변경할 수 있다.
const onSubmit = () => {
alert('submit 되었습니다');
};
const Keyup = (event) => {
if(event.keyCode === 13){ //13은 enter 값
onSubmit();
}
//console.log('key up!');
};
const updateText = () => {
setText('Hello React');
}
return (
<div className="App">
<input type='text' onKeyUp={Keyup}/>
<button onClick={onSubmit}>Submit</button>
<br/><br/>
<span>{text}</span>
<button onClick={ updateText }>Update</button>
</div>
);
}
export default App;
{폼에서 useState 사용하기}
ex3) form에서 useState 사용하기
[function] src/App.js
onChange={ (e) => setUsername(e.target.value) }
import React, { useState } from 'react'; //추가
import './App.css';
function App() {
const [username, setUsername] = useState('');
const [password, setpassword] = useState('');
const onSubmit = () => {
alert(username + '/' + password +' submit 되었습니다');
};
return (
<div className="App">
<form onSubmit={onSubmit}>
<input placeholder="Username" value={username} onChange={ (e) => setUsername(e.target.value)} /> <br/>
<input placeholder="Password" value={password} onChange={ (e) => setpassword(e.target.value)} /> <br/>
<button type="submit">Login</button>
</form>
</div>
);
}
export default App;
{useEffect 사용하기}
- state 값이 바뀔때 마다 컴포넌트가 랜더링이 되고
- 컴포넌트가 재 랜더링이 될때마다 useEffect() 함수가 동작한다
useEffect를 사용하려면 페이지 상단에 { useEffect } 가 추가되어야 한다.
state값이 바뀌면 컴포넌트가 재 랜더링이 되는데, 이때 마다 자동으로 호출된다.
useEffect( () => {
// ...
});
ex4) useEffect의 자동호출
[Function] src/App.js
import React, { useEffect, useState } from 'react'; //추가
import './App.css';
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count);
});
const increment = () => {
setCount(count+1);
};
return (
<div className="App">
<h1>Hello React!</h1>
<button onClick={increment}>Click</button>
</div>
);
}
export default App;
ex4-1) useEffect의 매개변수
- 두 번째 매개변수로 state변수를 사용하면 해당 state변수 값이 바뀔때만 useEffect() 함수가 동작한다
useEffect(() => {
// 처리코드
} , [state변수])
- 두 번째 매개변수를 아무것도 주지 않으면 최초 한번만 (초기화) 동작된다
useEffect(() => {
// 처리코드
} , [])
[Function] src/App.js
콘솔에 보면 '최초 한번만 실행'이 2번 찍혀있는데,
index.js 에 <React.StrictMode> 때문이라고 한다. 지우면 한번만 찍히는데, 크게 상관 없다.
import React, { useEffect, useState } from 'react'; //추가
import './App.css';
function App() {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
useEffect(() => {
console.log(count + ' ' + count2);
}, [count, count2]);
useEffect(() => {
console.log('최초 한번만 실행');
}, []);
const increment = () => {
setCount(count+1);
};
const increment2 = () => {
setCount2(count2+1);
};
return (
<div className="App">
<h1>Hello React!</h1>
<button onClick={increment}>Click</button>
<button onClick={increment2}>Click2</button>
</div>
);
}
export default App;
{컴포넌트로 만들기}
ex5)컴포넌트를 만들지 않았을때
[Function] src/App.js
import React, { useState } from 'react'; //추가
import './App.css';
function App() {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
const [count3, setCount3] = useState(0);
const increment = () => {
setCount(count+1);
};
const increment2 = () => {
setCount2(count2+1);
};
const increment3 = () => {
setCount3(count3+1);
};
return (
<div className="App">
<h1>Hello React!</h1>
<button onClick={increment}>Click {count}</button>
<button onClick={increment2}>Click {count2}</button>
<button onClick={increment3}>Click {count3}</button>
</div>
);
}
export default App;
ex5-1)컴포넌트로 만들기 (import 방법)
- src/components 폴더를 만들고 -> Counter.js 파일을 만든다
- 컴포넌트는 첫글자를 대문자로 만든다
- 컴포넌트안에 JSX는 꼭 하나의 부모태그가 존재해야한다.
const Counter = () => {
return (
<div>
JSX문법 사용
</div>
);
};
- 부모 박스로 <React.Fragment> JSX문법 사용 </React.Fragment> 를 사용할 수 있다 (태그로 출력되지 않음)
return (
<React.Fragment>
<button onClick={increment}>Click {count}</button>
<span>{ count }</span>
</React.Fragment>
);
// 약식문법
return (
<>
<button onClick={increment}>Click {count}</button>
<span>{ count }</span>
</>
);
[Function] src/App.js
*같은 컴포넌트를 3개 불러오지만, 각각의 counter는 따로 매겨진다.
import Counter from './components/Counter';
import './App.css';
function App() {
return (
<div className="App">
<h1>Hello React!</h1>
<Counter></Counter>
<Counter></Counter>
<Counter></Counter>
</div>
);
}
export default App;
[Function] src/components/Counter.js
import React, { useState } from 'react';
const Counter = () =>{
const [count, setCount] = useState(0);
const increment = () => {
setCount(count+1);
};
return (
<>
<button onClick={increment}>Click {count}</button>
<span>{ count }</span>
</>
);
};
export default Counter;
{자식 컴포넌트에 데이터 보내기 Props}
- 부모 컴포넌트에서 자식 콤퍼넌트로 데이터를 보낼 때 Props 사용한다. (속성과 비슷)
- 서브 컴포넌트의 함수에 매개변수로 props 를 준다
const Counter = (props) =>{
// ...
}
ex6) Props 처리
[Function] src/App.js
import Counter from './components/Counter';
import './App.css';
function App() {
return (
<div className="App">
<h1>Hello React!</h1>
<Counter></Counter>
<Counter data="click1" num="1"></Counter>
<Counter data="click2" num="10"></Counter>
<Counter data="click3" num="100"></Counter>
</div>
);
}
export default App;
[Function] src/components/Counter.js
ES6 문법
const clickString = props.data || 'click'; // 참일때 || 거짓일때
// props.data가 없으면 'click'을 할당한다.
import React, { useState } from 'react';
const Counter = (props) => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count+ Number(props.change));
};
const clickString = props.data || 'Click'; // 참일때 || 거짓일때 ES6
return (
<>
<button onClick={increment}>{clickString}</button>
<span>{count}</span>
</>
);
};
export default Counter;
ex6-1) state값 보내기/ 변경
- Props에 문자값이 아니라 state변수나 함수를 전달할때는 <콤퍼넌트 Props명={state변수} /> 로 {}를 사용한다
<Counter data={buttonName}></Counter>
[Function] src/App.js
import React, { useState } from 'react';
import Counter from './components/Counter';
import './App.css';
function App() {
const [buttonName, setButtonName] = useState('난 바뀔거야');
const clickButton = () =>{
setButtonName('바꼈다!!!');
};
return (
<div className="App">
<h1>Hello React!</h1>
<Counter data="Click1"></Counter>
<Counter data={buttonName}></Counter>
<Counter data="Click3"></Counter>
<button onClick={clickButton}>확인</button>
</div>
);
}
export default App;
[Function] src/components/Counter.js
import React, { useState } from 'react';
const Counter = (props) =>{
const [count, setCount] = useState(0);
const increment = () => {
setCount(count+1);
};
const clickString = props.data || 'Click'; // 참일때 || 거짓일때 ES6
return (
<>
<button onClick={increment}>{clickString}</button>
<span>{count}</span>
</>
);
};
export default Counter;
{React 조건 렌더링}
ex7) toggle 콘텐츠 만들기 (state 사용)
[Function] src/App.js
import React, { useState } from 'react';
import './App.css';
function App() {
const [condition, setCondition] = useState(false);
const toggle = () =>{
setCondition(!condition);
};
return (
<div className="App">
<h1>Hello React!</h1>
{condition ? <div>TRUE</div> : <div>FALSE</div>}
<button onClick={toggle}>toggle버튼</button>
</div>
);
}
export default App;
또는
import React, { useState } from 'react';
import './App.css';
function App() {
const [condition, setCondition] = useState(false);
const toggle = () =>{
setCondition(!condition);
};
const renderCondition = condition ? 'TRUE??' : 'FALSE??';
return (
<div className="App">
<h1>Hello React!</h1>
<div>{renderCondition}</div>
<button onClick={toggle}>toggle버튼</button>
</div>
);
}
export default App;
{React 반복문}
ex8) 반복문을 사용하지 않았을때
[Function] src/App.js
import React, { useState } from 'react';
import './App.css';
function App() {
const movies = [
{title:'반지의제왕', year: 2000},
{title:'왕의남자', year: 2010},
{title:'터미네이터', year: 2020}
];
return (
<div className="App">
<h1>Movie List</h1>
<div className="movie">
<div className="movie-title">제목 : {movies[0].title}</div>
<div className="movie-year">개봉년도 : {movies[0].year}년</div>
</div>
<div className="movie">
<div className="movie-title">제목 : {movies[1].title}</div>
<div className="movie-year">개봉년도 : {movies[1].year}년</div>
</div>
<div className="movie">
<div className="movie-title">제목 : {movies[2].title}</div>
<div className="movie-year">개봉년도 : {movies[2].year}년</div>
</div>
</div>
);
}
export default App;
src/App.css
body{font-family: Arial, Helvetica, sans-serif;font-size: 20px}
.movie{display: flex; align-items: center;border:1px solid #666; padding: 10px; border-radius: 5px;margin-bottom: 5px}
.movie .movie-title{flex-grow:1}
.movie .movie-year{color: red; font-size:.95rem}
ex8-1) 반복문 사용 (for문)
[Function] src/App.js
https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- DOM을 사용하는 innerHTML은 문법에러가 발생한다. (JSX보다 JS가 먼저(위에) 위치해 있기 때문에 처리 순서에 따른 에러가 난다.)
- JSX 영역에 dangerouslySetInnerHTML={{ __html: randerMovies }} 문법을 사용한다.
- 해당 영역에 들어갈 HTML에는 className 대신 class를 사용한다.
import './App.css';
function App() {
const movies = [
{title:'반지의제왕', year: 2000},
{title:'왕의남자', year: 2010},
{title:'터미네이터', year: 2020}
];
let randerMovies = "";
for(let i=0; i<movies.length; i++){
randerMovies +=`<div class="movie">
<div class="movie-title">제목 : ${movies[i].title}</div>
<div class="movie-year">개봉년도 : ${movies[i].year}년</div>
</div>`;
}
// document.getElementById('con').innerHTML = randerMovies;
// dom에 관련된 JS정규문법을 사용할 수 없다.
return (
<div className="App">
<h1>Movie List</h1>
<div id="con" dangerouslySetInnerHTML={{ __html: randerMovies }}></div>
</div>
);
}
export default App;
ex8-2) 반복문 사용 (.map() 사용) ★★★★★
ES6 배열함수 map() 문법을 참조한다.
https://ooo-k.tistory.com/241?category=893627
* key={movie.title} 키값을 주지않으면 에러가 발생한다.
해당 키 값을 준다(주로 id같은 키가 주로 사용된다)
[Function] src/App.js
import './App.css';
function App() {
const movies = [
{title:'반지의제왕', year: 2000},
{title:'왕의남자', year: 2010},
{title:'터미네이터', year: 2020}
];
const randerMovies = movies.map(movie => {
return(
<div className="movie" key={movie.title}>
<div className="movie-title">제목 : {movie.title}</div>
<div className="movie-year">개봉년도 : {movie.year}년</div>
</div>
);
});
return (
<div className="App">
<h1>Movie List</h1>
{randerMovies}
</div>
);
}
export default App;
ex8-3) 컴포넌트와 props 데이터 보내기 종합
- components/Movie.js 파일을 만든다 (컴포넌트 만들기)
src/components/Movie.js
import React, { useState } from 'react';
const Movie = (props) =>{
return (
<div className="movie">
<div className="movie-title">제목 : {props.mov.title}</div>
<div className="movie-year">개봉년도 : {props.mov.year}년</div>
</div>
);
};
export default Movie;
src/App.js
import React, { useState } from 'react';
import Movie from './components/Movie';
import './App.css';
function App() {
const movies = [
{title:'반지의제왕', year: 2000},
{title:'왕의남자', year: 2010},
{title:'터미네이터', year: 2020}
];
const randerMovies = movies.map(movie => {
return(
<Movie mov={movie} key={movie.title} />
);
});
return (
<div className="App">
<h1>Movie List</h1>
{randerMovies}
</div>
);
}
export default App;
또는(props 중에서 mov만 가져오면 props. 을 생략할 수 있다)
src/components/Movie.js
import React, { useState } from 'react';
const Movie = ({ mov }) =>{
return (
<div className="movie">
<div className="movie-title">제목 : {mov.title}</div>
<div className="movie-year">개봉년도 : {mov.year}년</div>
</div>
);
};
export default Movie;
React router 설치하기
React-Router 란
리액트는 SPA (Single Page Application) 방식으로서,
여러개의 페이지를 사용하며, 새로운 페이지를 로드하는 기존의 MPA 방식과 달리
새로운 페이지를 로드하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가집니다.
https://reactrouter.com/ 에서 web 버튼을 클릭하면 npm을 확인할 수 있다
https://reactrouter.com/docs/en/v6/getting-started/installation
[참고] https://m.blog.naver.com/sejun3278/221797203201 //React router 설명 블로그
설치하기
- react router DOM 을 사용하기 위해서는 npm install react-router-dom (최신버전)을 설치한다
- 이 예제는 npm install react-router-dom@5.3.0 으로 설치한다
npm install react-router-dom
// 또는
$ npm install react-router-dom@6
// 아래 예제는
npm install react-router-dom@5.3.0
// 으로 설치한다.
- package.json 파일을 열어보면 설치된 패키지 목록을 볼 수 있다
사용하기
index.js 파일에 추가한다.
import {BrowserRouter , Route} from 'react-router-dom';
root.render 변경
<BrowserRouter>
<App />
</BrowserRouter>
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import {BrowserRouter , Route} from 'react-router-dom'; // 추가한다
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
ex1) Router 사용하기
src/App.js
exact 옵션은 '정확히 일치하는' 이다. 경로가 중복될때 사용 (아래 예제는 / 가 중복됨)
<Route exact path="/"><Home></Home></Route>
import React, { useState } from 'react';
import {BrowserRouter , Route} from 'react-router-dom'; //추가한다
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
function Topics(){ //Topics 페이지
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App() {
return (
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/Topics">Topics</a></li>
<li><a href="/Contact">Contact</a></li>
</ul>
{/* <Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route> */}
<Route exact path="/" component={Home}></Route>
<Route path="/Topics" component={Topics}></Route>
<Route path="/Contact" component={Contact}></Route>
</div>
);
}
export default App;
ex2) Switch 컴포넌트 사용 (굳이..?)
import {BrowserRouter , Route, Switch} from 'react-router-dom'; //추가
src/App.js
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch} from 'react-router-dom'; //추가
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
function Topics(){ //Topics 페이지
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/Topics">Topics</a></li>
<li><a href="/Contact">Contact</a></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
</Switch>
</div>
)
};
export default App;
ex3) Link 컴퍼넌트 (비동기처리)
- 라우팅을 페이지의 리로드 없이 처리해준다
- import {BrowserRouter , Route, Switch, Link} from 'react-router-dom'; //추가
- <a href="/">Home</a> 태그 대신에 <Link to="/">Home</Link> 로 수정
src/App.js
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch, Link} from 'react-router-dom'; // link 추가
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
function Topics(){ //Topics 페이지
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/Topics">Topics</Link></li>
<li><Link to="/Contact">Contact</Link></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</div>
)
};
export default App;
ex4) NavLink 컴퍼넌트 ★★★★★
- import {BrowserRouter , Route, Switch, Link, NavLink} from 'react-router-dom'; //추가
- <NavLink exact to="/">Home</NavLink>
- NavLink를 사용하면 class="active" 라는 클래스가 자동으로 생성된다
- 개발자 도구를 통해서 확인하면
<a href="/Contact" aria-current="page" class="active">Contact</a> 로 처리된다
- App.css 파일을 열어서 .active{font-weight: bold; color:red;} 추가
src/App.js
import React, { useState } from 'react';
import {Route, Switch, NavLink} from 'react-router-dom';
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
function Topics(){ //Topics 페이지
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</div>
)
};
export default App;
src/App.css
body{font-family: Arial, Helvetica, sans-serif;font-size: 20px}
.movie{display: flex; align-items: center;border:1px solid #666; padding: 10px; border-radius: 5px;margin-bottom: 5px}
.movie .movie-title{flex-grow:1}
.movie .movie-year{color: red; font-size:.95rem}
.active{font-weight: bold; color:red; background-color: black;}
{Router 중첩 과 Parameter}
ex5) Router 중첩
function Topics(){} 에 서브 라우터 중첩
path 값에 유의하자
src/App.js
import React, { useState } from 'react';
import {Route, Switch, NavLink} from 'react-router-dom';
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
function Topics(){ //Topics 페이지
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
<ul>
<li><NavLink exact to="/topics/1">HTML</NavLink></li>
<li><NavLink to="/topics/2">JS</NavLink></li>
<li><NavLink to="/topics/3">React</NavLink></li>
</ul>
<Switch>
<Route exact path="/topics/1">
<p>HTML is ...</p>
</Route>
<Route path="/topics/2">
<p>JS is ...</p>
</Route>
<Route path="/topics/3">
<p>React is ...</p>
</Route>
</Switch>
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</div>
)
};
export default App;
ex5-1) 객체배열과 for문으로 링크처리
src/App.js
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch, Link, NavLink} from 'react-router-dom';
import './App.css';
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
//객체 배열 생성
var contents = [
{id:1 , title:'HTML' , desc:'HTML is ...'},
{id:2 , title:'JS' , desc:'JS is ...'},
{id:3 , title:'React' , desc:'React is ...'}
]
function Topics(){ //Topics 페이지
var lis=[];
// 반복문으로 list 처리
for(var i=0; i<contents.length;i++){
lis.push(
<li key={contents[i].id}>
<NavLink exact to={'/topics/'+contents[i].id}>{contents[i].title}</NavLink>
</li>
);
}
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
<ul>
{lis}
</ul>
<Switch>
<Route exact path="/topics/1">
{contents[0].desc}
</Route>
<Route path="/topics/2">
{contents[1].desc}
</Route>
<Route path="/topics/3">
{contents[2].desc}
</Route>
</Switch>
</div>
)
};
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</div>
)
};
export default App;
ex5-3) 콤퍼넌트 파일로 처리
components 폴더에 Home.js , Topics.js , Contact.js 파일을 만든다
src/App.js
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch, Link, NavLink, useParams} from 'react-router-dom';
import Home from './components/Home'; //추가
import Topics from './components/Topics'; //추가
import Contact from './components/Contact'; //추가
import './App.css';
function App(){
return(
<div>
<h1>Hello React Router DOM</h1>
<ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul>
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</div>
)
};
export default App;
src/components/Home.js
function Home(){ //메인페이지
return(
<div>
<h2>Home</h2>
home..내용 페이지
</div>
)
};
export default Home;
src/components/Topics.js
import {BrowserRouter , Route, Switch, Link, NavLink, useParams} from 'react-router-dom';
//객체 배열 생성
var contents = [
{id:1 , title:'HTML' , desc:'HTML is ...'},
{id:2 , title:'JS' , desc:'JS is ...'},
{id:3 , title:'React' , desc:'React is ...'}
]
function Topic(){
var params = useParams();
//console.log(params);
var topic_id = params.topic_id;
var selected_topic ={
title:'Sorry', desc:'Not Found'
}
for(var i=0; i<contents.length;i++){
if(contents[i].id === Number(topic_id)){
selected_topic = contents[i];
break;
}
}
return(
<div>
<h3>{selected_topic.title}</h3>
{selected_topic.desc}
</div>
);
};
function Topics(){ //Topics 페이지
var lis=[];
for(var i=0; i<contents.length;i++){
lis.push(
<li key={contents[i].id}>
<NavLink exact to={'/topics/'+contents[i].id}>{contents[i].title}</NavLink>
</li>
);
}
return(
<div>
<h2>Topics</h2>
Topics..내용 페이지
<ul>
{lis}
</ul>
<Route path="/topics/:topic_id">
<Topic></Topic>
</Route>
</div>
);
};
export default Topics;
src/components/Contact.js
function Contact(){ //Contact 페이지
return(
<div>
<h2>Contact</h2>
Contact..내용 페이지
</div>
)
};
export default Contact;
{ 라우터 사용의 다른 방법 }
- 구글에서 bootstrap cdn 검색 -> https://www.bootstrapcdn.com/
해당 버전의 css-> html , JavaScript-> html 을 선택하면
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
- public-> index.html을 열고 위의 코드를 추가한다 (<script>는 <body>의 가장 마지막에 추가한다)
public/html.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
</body>
</html>
- https://getbootstrap.com/docs/5.1/components/navbar/ 네비게이션바 코드를 복사한다
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
src/App.js 에 nav를 추가한다
class를 className으로 변경한다.
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch, Link, NavLink, useParams} from 'react-router-dom';
import Home from './components/Home'; //추가
import Topics from './components/Topics'; //추가
import Contact from './components/Contact'; //추가
import './App.css';
function App(){
return(
<div>
<header>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<div className="container-fluid">
<NavLink exact to="/" className="navbar-brand">Logo</NavLink>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className="nav-item">
<NavLink exact to="/" className="nav-link" aria-current="page">Home</NavLink>
</li>
<li className="nav-item">
<NavLink to="/Topics" className="nav-link">Topics</NavLink>
</li>
<li className="nav-item">
<NavLink to="/Contact" className="nav-link">Contact</NavLink>
</li>
</ul>
</div>
</div>
</nav>
</header>
{/* <ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul> */}
<article id="content">
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</article>
</div>
)
};
export default App;
{ json 파일 불러와서 data 출력하기 }
ex6) JSONPlaceholder 를 사용한 user data 받아오기
src/customers.json
[
{"Name":"Alfreds Futterkiste","City":"Berlin","Country":"Germany"},
{"Name":"Ana Trujillo Emparedados y helados","City":"México D.F.","Country":"Mexico"},
{"Name":"Antonio Moreno Taquería","City":"México D.F.","Country":"Mexico"},
{"Name":"Around the Horn","City":"London","Country":"UK"},
{"Name":"B's Beverages","City":"London","Country":"UK"},
{"Name":"Berglunds snabbköp","City":"Luleå","Country":"Sweden"},
{"Name":"Blauer See Delikatessen","City":"Mannheim","Country":"Germany"},
{"Name":"Blondel père et fils","City":"Strasbourg","Country":"France"},
{"Name":"Bólido Comidas preparadas","City":"Madrid","Country":"Spain"},
{"Name":"Bon app'","City":"Marseille","Country":"France"},
{"Name":"Bottom-Dollar Marketse","City":"Tsawassen","Country":"Canada"},
{"Name":"Cactus Comidas para llevar","City":"Buenos Aires","Country":"Argentina"},
{"Name":"Centro comercial Moctezuma","City":"México D.F.","Country":"Mexico"},
{"Name":"Chop-suey Chinese","City":"Bern","Country":"Switzerland"},
{"Name":"Comércio Mineiro","City":"São Paulo","Country":"Brazil"}
]
src/components.Home.js
import React from 'react';
import customers from './../customers.json';
function Home() {
let customerData = customers.map((row,index) => {
return(
<tr key={index}>
<td>{row.Name}</td>
<td>{row.City}</td>
<td>{row.Country}</td>
</tr>
);
});
return (
<>
<h2>Home</h2>
<table className="table table-bordered">
<thead>
<tr><th>Name</th><th>City</th><th>Country</th></tr>
</thead>
<tbody>
{customerData}
</tbody>
</table>
</>
);
}
export default Home;
src/App.js
import React, { useState } from 'react';
import {BrowserRouter , Route, Switch, Link, NavLink, useParams} from 'react-router-dom';
import Home from './components/Home'; //추가
import Topics from './components/Topics'; //추가
import Contact from './components/Contact'; //추가
import './App.css';
function App(){
return(
<div>
<header>
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<div className="container-fluid">
<NavLink exact to="/" className="navbar-brand">Logo</NavLink>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav">
<li className="nav-item">
<NavLink exact to="/" className="nav-link" aria-current="page">Home</NavLink>
</li>
<li className="nav-item">
<NavLink to="/Topics" className="nav-link">Topics</NavLink>
</li>
<li className="nav-item">
<NavLink to="/Contact" className="nav-link">Contact</NavLink>
</li>
</ul>
</div>
</div>
</nav>
</header>
{/* <ul>
<li><NavLink exact to="/">Home</NavLink></li>
<li><NavLink to="/Topics">Topics</NavLink></li>
<li><NavLink to="/Contact">Contact</NavLink></li>
</ul> */}
<article id="content">
<Switch>
<Route exact path="/"><Home></Home></Route>
<Route path="/Topics"><Topics></Topics></Route>
<Route path="/Contact"><Contact></Contact></Route>
<Route path="/">Not found</Route>
</Switch>
</article>
</div>
)
};
export default App;
Semantic UI React
- https://react.semantic-ui.com/usage (공식사이트)
NPM 설치하기
버전이 맞지 않으면 에러가 난다. (에러남..)
$ npm install semantic-ui-react semantic-ui-css
<index.js> 파일에 import 'semantic-ui-css/semantic.min.css'; // 추가
import 'semantic-ui-css/semantic.min.css';
CDN 사용하기
* 설치에 문제가 생기면 ...
- index.html 파일에
<body> 태그 가장 아래에 두줄의 코드를 추가한다(CDN)
<link async rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2/dist/semantic.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-react/dist/umd/semantic-ui-react.min.js"></script>
public/index.html
에러남..
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<link async rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2/dist/semantic.min.css"/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-react/dist/umd/semantic-ui-react.min.js"></script>
</body>
</html>
ex5)Accordion Fluid 적용하기
https://react.semantic-ui.com/modules/accordion/
배포하는 방법
1. package.json 파일에 경로 설정을 추가한다.
경로 설정을 하지 않으면 빌드 된 파일들의 경로가 맞지 않는다.
"homepage": "./",
2. npm run build
npm run build
build폴더가 만들어지고 빌드된 파일들이 저장된다. 이 파일들을 실제 배포하면 된다.(용량의 최적화 등)
'Study > JavaScript' 카테고리의 다른 글
ES6 배열 내장 함수 (0) | 2022.04.26 |
---|---|
Momentum (0) | 2022.04.25 |
Vue JS (1) | 2022.04.08 |
Angular JS (0) | 2022.04.06 |
마우스 휠 중복 과다 제어 막기 (0) | 2022.03.24 |