React : Facebook에서 만든 Javascript UI Library
Component : 사용자 정의 태그
1. 가독성
2. 재사용성
3. 유지보수
https://reactjs.org/docs/create-a-new-react-app.html#create-react-app
> npm install -g create-react-app@2.1.8
-g : 터미널 어디에서나 사용 가능!
맥 : sudo 추가
C:\Users\user\Desktop\dev\expo\myNewProject>create-react-app
Please specify the project directory:
create-react-app <project-directory>
For example:
create-react-app my-react-app
Run create-react-app --help to see all options.
이렇게 뜨면 성공!
C:\Users\user\Desktop\react-app>create-react-app .
Creating a new React app in C:\Users\user\Desktop\react-app.
Quick Overview 의 npx는 항상 최신버전을 해주기 때문에 실무에서 추천!
아무든 create-react-app 해주고 vscode 켜고 그 위치에서
npm start 해주면 웹브라우저 뜸!
7/40 부터
https://www.inflearn.com/course/react-%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9/lecture/20305
App.js를 다음과 같이 class type으로 변경!
import React, { Component} from 'react';
// import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Apfdp from './App'; ///!!!!!!!!!!!!!!여기랑
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<Apfdp />, document.getElementById('root')); ///!!!!!!!!!!!!!!여기랑
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
// ///!!!!!!!!!!!!!!여기랑 이름만 같으면 됨,, 대신 ./App 이건 파일이름이라 바꾸면 안되겠지
새로고침 우클릭 -> 캐시 비우기 및~~~ 그거 용량 엄청 커 배포할 땐 이러면 ㅇ안되겠지
npm run start
빌드할 때는 npm run build (배포 느낌)
그러면 build폴더생김
create react app이 불필요한 용량 다 없앰.
실제로 배포할 땐 build에 있는 파일들을 하면됨
npm install -g serve : npm을 통해 설치할 수 있는 웹 서버
serve 명령어 통해 웹서버 설치 가능
npx serve -s build : build 폴더를 배포하겠다!?
npx serve -s build하고 다시 개발자도구 켜서 로컬 웹페이지에서 용량 확인해보면
용량이 줄어들었다!
이전에는 1.7MB였었는디
====대망의 component====
10/40
https://reactjs.org/docs/components-and-props.html
만든 컴포넌트에 각각 다른 속성을 적용하고 싶을 때! 다 문서에 있음여
class Subject extends Component {
// class 안에 있는 함수는 function 생략
render() { // 필수 함수
return ( // 컴포넌트는 하나의 최상위 태그만 쓴다
<header>
<h1> {this.props.title} </h1>
{this.props.sub}
</header>
);
}
}
// 유사 자바스크립트
// JSX : "" 이런거 안따지고 쓸 수 있도록 Facebook에서 만든 유사 자바스크립트!
class App extends Component {
render() {
return (
<div className="App">
<Subject title="WEB" sub="sub~!"></Subject>
<Subject title="WEB2" sub="sub~!2"></Subject>
<TableOfContent />
<Content />
</div>
);
}
}
이것이 바로 리팩토링!
React에서는 title, sub 같은 것을 props라고 한다.
나 이제 React 할 수 있어!
14/40
1. 설명서 볼 줄 알기!
2. 여러 가지 가설을 통해 1에서 알아낼 수 없는 부분을 터득하기! state!
3. 질문
4. 검색
state!!!
https://reactjs.org/community/support.html
Community - Tools - Debuging
React로 만들어진 앱의 상태 볼 수 있다.
React Developer Tools 확장 프로그램 설치!
그러면 개발자도구 Element에서 맨 끝에 React 보면 React상의 코드로 볼 수가 있다!!! 오마이!!
componet 분리!
src 아래 components 폴더 만든다
import React, { Component} from 'react';
import './App.css';
import TableOfContent from './components/TitleOfContent';
import Content from './components/Content';
import Subject from './components/Subject';
// 유사 자바스크립트
// JSX : "" 이런거 안따지고 쓸 수 있도록 Facebook에서 만든 유사 자바스크립트!
class App extends Component {
render() {
return (
<div className="App">
<Subject title="WEB" sub="sub~!"></Subject>
<Subject title="WEB2" sub="sub~!2"></Subject>
<TableOfContent />
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
</div>
);
}
}
export default App;
이런식으로 사용!
각각의 Table~ Co~ Su~ 이파일들은
각각 이렇게 생겼음
import React, { Component} from 'react';
// 없어도 되면 되는거고 있어야하면 있어야해
class TableOfContent 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 TableOfContent; // 이제 다른 곳에서 사용 가능@
오케이~~
=====state=====
state는 props라는 개념과 같이 봐야 한다.
props는 사용자가 컴포넌트 사용할 때 중요
state는 props값에 따라 내부 구현값 달라지는?? 그런게 중요
props는 사용자에게 중요한 정보
사용자가 알 필요 없는 component 내부적으로 사용되는 것 : state
TableOfContent.js
import React, { Component} from 'react';
// 없어도 되면 되는거고 있어야하면 있어야해
class TableOfContent extends Component {
render() {
var lists = [];
var data = this.props.data;
var i = 0;
while (i < data.length) {
// key는 react가 필요해서 요청하는 것. 그냥 필요한거래
lists.push(<li key={data[i].id}><a href={"/content/" + data[i].id}>{data[i].title}</a></li>);
i = i + 1;
}
return (
<nav>
<ul>
{lists}
</ul>
</nav>
);
}
}
// 어떤 것을 외부에서 사용할 수 있도록 할 것인가?
export default TableOfContent; // 이제 다른 곳에서 사용 가능@
App.js
import React, { Component} from 'react';
import './App.css';
import TableOfContent from './components/TitleOfContent';
import Content from './components/Content';
import Subject from './components/Subject';
// 유사 자바스크립트
// JSX : "" 이런거 안따지고 쓸 수 있도록 Facebook에서 만든 유사 자바스크립트!
class App extends Component {
constructor(props) { // state 값 초기화 그리고 세팅
super(props); // render보다 먼저 실행되는 함수
this.state = {
subject: {title: 'WEB from state', sub: 'World Wisssde Web!'},
contents: [
{id: 1, title: 'HTML', desc: 'HTML is HyperText ...'},
{id: 2, title: 'CSS', desc: 'CSS is for design'},
{id: 3, title: 'JavaScript', desc: 'JavaScript is for interactive'}
]
}
}
render() {
return ( // 자바스크립트의 코드로서 실행되게 하고 싶으면 {} 아니면 문자열인 ""
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject>
<TableOfContent data={this.state.contents} />
<Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
</div>
);
}
}
export default App;
state 어떻게 쓰는지 반복문 어떻게 쓰는지!
[event]
App.js
import React, { Component} from 'react';
import './App.css';
import TableOfContent from './components/TitleOfContent';
import Content from './components/Content';
import Subject from './components/Subject';
// 유사 자바스크립트
// JSX : "" 이런거 안따지고 쓸 수 있도록 Facebook에서 만든 유사 자바스크립트!
class App extends Component {
constructor(props) { // state 값 초기화 그리고 세팅
super(props); // render보다 먼저 실행되는 함수
this.state = {
mode: 'welcome',
subject: {title: 'WEB', sub: 'This is Subject!'},
welcome: {title: 'Welcome', desc: 'World Wide Web!'},
contents: [
{id: 1, title: 'HTML', desc: 'HTML is HyperText ...'},
{id: 2, title: 'CSS', desc: 'CSS is for design'},
{id: 3, title: 'JavaScript', desc: 'JavaScript is for interactive'}
]
}
}
// props나 state가 바뀌면 해당 render함수가 다시 호출된다. 화면이 다시 그려진다.
render() {
console.log('App 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) {
console.log(e);
e.preventDefault(); // a 태그의 기본적인 동작을 금지한다. like reload
// 첫번째 파라미터 : event
alert('hi'); // reload됨
}}>{this.state.subject.title}</a> </h1>
{this.state.subject.sub}
</header>
<TableOfContent data={this.state.contents} />
<Content title={_title} desc={_desc}></Content>
</div>
);
}
}
export default App;
e.prevent를 주목!
지금 우리는 a 태그를 클릭하면 App component의 mode를 welcome으로 바꿀거야를 할건데 reload를 막기위해 저 함수를 쓴 것!
<h1> <a href="/" onClick={function(e) {
// 첫번째 파라미터 : event
// alert('hi'); // reload됨
console.log(e);
e.preventDefault(); // a 태그의 기본적인 동작을 금지한다. like reload
this.state.mode = 'welcome';
// this의 값이 자기자신 component를 가리키는 것이 x rid 아무것도 없음
}.bind(this)}>{this.state.subject.title}</a> </h1>
this가 자기자신 가리키려면 .bind(this)라고 해야돼.
근데 이렇게 해도 안돼.
<h1> <a href="/" onClick={function(e) {
// 첫번째 파라미터 : event
// alert('hi'); // reload됨
console.log(e);
e.preventDefault(); // a 태그의 기본적인 동작을 금지한다. like reload
//this.state.mode = 'welcome';
// this의 값이 자기자신 component를 가리키는 것이 x rid 아무것도 없음
this.setState({
mode: 'welcome'
});
}.bind(this)}>{this.state.subject.title}</a> </h1>
이렇게 setState로 해줘야 state가 바뀜!
그럼 이제 a 태그 누르면 mode state가 바뀌어서 _title이랑 _desc가 바뀌겠지
[bind]
class App extends Component {
constructor(props) { // state 값 초기화 그리고 세팅
super(props); // render보다 먼저 실행되는 함수
this.state = {
mode: 'read',
subject: {title: 'WEB', sub: 'This is Subject!'},
welcome: {title: 'Welcome', desc: 'World Wide Web!'},
contents: [
{id: 1, title: 'HTML', desc: 'HTML is HyperText ...'},
{id: 2, title: 'CSS', desc: 'CSS is for design'},
{id: 3, title: 'JavaScript', desc: 'JavaScript is for interactive'}
]
}
}
// props나 state가 바뀌면 해당 render함수가 다시 호출된다. 화면이 다시 그려진다.
render() {
console.log('App 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;
}
console.log('render', this); // render 안에서 this는 App 컴포넌트 전체를 가리킨다
return ( // 자바스크립트의 코드로서 실행되게 하고 싶으면 {} 아니면 문자열인 ""
<div className="App">
{/* <Subject
title={this.state.subject.title}
sub={this.state.subject.sub}>
</Subject> */}
<header>
<h1> <a href="/" onClick={function(e) {
// 첫번째 파라미터 : event
// alert('hi'); // reload됨
console.log('event in', this);
e.preventDefault();
return;
console.log(e);
e.preventDefault(); // a 태그의 기본적인 동작을 금지한다. like reload
this.state.mode = 'welcome';
// this의 값이 자기자신 component를 가리키는 것이 x rid 아무것도 없음
this.setState({
mode: 'welcome'
});
}}>{this.state.subject.title}</a> </h1>
{this.state.subject.sub}
</header>
<TableOfContent data={this.state.contents} />
<Content title={_title} desc={_desc}></Content>
</div>
);
}
}
export default App;
render() 아래 this는 App 컴포넌트 전체를 가리키는데
header 안에서 return 위에 로그를 찍어보면 event in 은 undefined다.
그래서 .bind(this)를 위에서처럼 해줘야 강제로 this에 컴포넌트를 주입시킬 수 있다.
이런 느낌
이해 안가면 그냥 이렇게 쓰면 된다는걸 알기!
24/40
이벤트를 우리가 직접 만들어보자!
Subject에 onChangePage 이벤트를 직접!
App.js
return ( // 자바스크립트의 코드로서 실행되게 하고 싶으면 {} 아니면 문자열인 ""
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function() {
this.setState({mode: 'welcome'});
}.bind(this)}>
</Subject>
<TableOfContent data={this.state.contents} />
<Content title={_title} desc={_desc}></Content>
</div>
);
우리가 onChangePage라는 이벤트를 정의한 것! 저거는 mode를 welcome으로 바꾸는 함수야. 저게 props로 들어기ㅏ
Subject.js
import React, { Component} from 'react';
class Subject extends Component {
// class 안에 있는 함수는 function 생략
render() { // 필수 함수
console.log('Subject 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;
그럼 여기서 onClick을 한다는건 a태그를 클릭했다는거지 그러면 이제 preventDefault를 하고 속성으로 있는
onChangePage 이벤트를 실행시켜! 그럼 mode가 welcome으로 바뀌겠지!
이제 id마다 맞는 desc를 출력해줄거야 그러면 각각의 id를 불러올 줄 알아야겠지?
TableOfContent.js
import React, { Component} from 'react';
// 없어도 되면 되는거고 있어야하면 있어야해
class TableOfContent extends Component {
render() {
console.log('TableOfContent Render');
var lists = [];
var data = this.props.data;
var i = 0;
while (i < data.length) {
// key는 react가 필요해서 요청하는 것. 그냥 필요한거래
lists.push(
<li key={data[i].id}>
<a
href={"/content/" + data[i].id}
data-id={data[i].id}
onClick={function(e) {
// debugger;
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}.bind(this)}
>
{data[i].title}
</a>
</li>);
i = i + 1;
}
return (
<nav>
<ul>
{lists}
</ul>
</nav>
);
}
}
// 어떤 것을 외부에서 사용할 수 있도록 할 것인가?
export default TableOfContent; // 이제 다른 곳에서 사용 가능@
a 태그에 dataId랑 onClick 속성!
근데 dataset이라는거 쓰려면 data- 이렇게 써야해
debugger;
이거 잘 이용하기
debugger로 딱 멈춘 순간 esc 누르면 console이 나옴
그 콘솔에서 e 입력하면 현재 event에 뭐가 들어있는지 볼 수 있다
거기에서 target이 있응께 selectedContentId라는 속성을 쓸 수 있겠지! 어디서? App.js의 onChangePage()함수에서!
App.js
import React, { Component} from 'react';
import './App.css';
import TableOfContent from './components/TitleOfContent';
import Content from './components/Content';
import Subject from './components/Subject';
// 유사 자바스크립트
// JSX : "" 이런거 안따지고 쓸 수 있도록 Facebook에서 만든 유사 자바스크립트!
class App extends Component {
constructor(props) { // state 값 초기화 그리고 세팅
super(props); // render보다 먼저 실행되는 함수
this.state = {
mode: 'read',
selectedContentId: 2,
subject: {title: 'WEB', sub: 'This is Subject!'},
welcome: {title: 'Welcome', desc: 'World Wide Web!'},
contents: [
{id: 1, title: 'HTML', desc: 'HTML is HyperText ...'},
{id: 2, title: 'CSS', desc: 'CSS is for design'},
{id: 3, title: 'JavaScript', desc: 'JavaScript is for interactive'}
]
}
}
// props나 state가 바뀌면 해당 render함수가 다시 호출된다. 화면이 다시 그려진다.
render() {
console.log('App 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') {
var i = 0;
while (i < this.state.contents.length) {
var data = this.state.contents[i];
if (data.id === this.state.selectedContentId) {
_title = data.title;
_desc = data.desc;
break; // end while
}
i = i + 1;
}
}
console.log('render', this); // render 안에서 this는 App 컴포넌트 전체를 가리킨다
return ( // 자바스크립트의 코드로서 실행되게 하고 싶으면 {} 아니면 문자열인 ""
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function() {
this.setState({mode: 'welcome'});
}.bind(this)}>
</Subject>
<TableOfContent
onChangePage={function(id) {
this.setState({
mode: 'read',
selectedContentId: Number(id)
});
}.bind(this)}
data={this.state.contents} />
<Content title={_title} desc={_desc}></Content>
</div>
);
}
}
export default App;
Number()는 숫자로 바꿔주는 JavaScript의 함수!
그러면 이제 li 클릭할 때 id의 값이 바뀌니까 render가 다시 되겠지 그때마다
break 있는 그 while문이 도니까 클릭할 때 state값이 바뀌니까 그때마다 맞느 ㄴDESC가 나오겠지!
그리고! bind의 매개변수를 이용하는 방법도 있다
<a
href={"/content/" + data[i].id}
// data-id={data[i].id}
onClick={function(id, num, e) {
// debugger;
e.preventDefault();
this.props.onChangePage(id);
}.bind(this, data[i].id, 10)}
>
{data[i].title}
</a>
주석 처리하고 bind에 매개변수와 function 매개변수 저렇게 한 칸씩 밀려서 e 는 맨마지막으로@
10은 그냥 이해를 위해 넣은 것
27/40 ㅇ정리 : props vs state & 상위-하위 하위-상위 이게 제일 중요해 ***
Props
component 안에서 자신의 속성의 값을 바꿀 수 없다!
Props State 모두 render함수 호출을 유발.
UI가 바뀌어야 한다면 두 개를 이용..!!
상위 컴포넌트가 하위에게 영향 : PROPS
하위가 상위 : event (li 클릭하면 selectedId가 바뀌었던 것 처럼!)
https://github.com/daheeahn/190623_ReactAppReiew
여기까지 만들어본 웹페이지 깃헙에 올려놓음!
28/40 현실 애플리케이션 만들긔!
'Develop > React Native' 카테고리의 다른 글
TDD 개발 방법론 (0) | 2019.09.14 |
---|---|
react-navigation (0) | 2019.07.07 |
[React/Inflearn] 리액트 처음이시라구요? React JS로 웹 서비스 만들기! (0) | 2019.06.24 |
[React Native/Inflearn] React Native로 ToDo 앱 만들기 (0) | 2019.06.24 |
[React Native/Inflearn] React 첫 입문 & React Native로 날씨앱 만들기 (2) | 2019.06.21 |