생활코딩님의 리액트앱 배포용으로 빌드하는법 수업을 들었는데 아주 유용했다.

그냥 실행했을때

그냥 npm start로 앱을 실행했을때

디버깅 네트워크 탭에 들어가서 확인해보면 2.5MB나 갖고오고 있는걸 확인하고있다.

 

터미널에 npm build라고 치면 여러 작업을 거쳐 builld라는폴더가 하나 생긴다.
기존 프로젝트 내용들을 꽉꽉 줄여서 build폴더에 넣어놓은 모습이다.

index.html파일을 봐도 전혀 바뀌어있다.

빌드된 파일을 실행시키려면 어떻게 해야되는지도 나와있다.

serve를 npm으로 깔고 실행해야되는데

깔기 싫으면 그냥 npx serve -s build 해도 된다.

npm은 계속 설치해놓고 쓰는거고
npx
는 설치하고 사용하고 바로 지운다.

실행하면 알림메시지가 뜬다. 5000포트로 접속하면

빌드한 후

갖고온 파일 크기가 작아진게 보인다. 앱 열심히 만들고 배포할 때는 빌드를 해주면 된다.

' > 리액트' 카테고리의 다른 글

[리액트]고객관리 시스템_프로젝트 생성  (0) 2019.09.01
[리액트]형상관리  (0) 2019.08.31
[리액트]이벤트 핸들러  (0) 2019.08.31
[리액트]props state  (0) 2019.08.31
[리액트]컴포넌트  (0) 2019.08.31

 

자식컴포넌트에서 발생한 이벤트를 부모컴포넌트에서 핸들링하고싶을때가 있다.

 

1.부모컴포넌트에 핸들링함수를 만든다.

2.자식컴포넌트에 props로 넘겨준다.

3.자식컴포넌트에서 이벤트 발생시 해당 props 함수를 호출한다. 필요한 값은 인자로 넘기면 된다.

컴포넌트끼리 핸들링함수의 인자를 통해 연결된다.

<App.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css"//일케해놓으면 App 컴포넌트가 로드될때 같이 import돼서 쓸수있게된다. 즉 <App/> 얘가 쓰일때
//css가 따라오게끔. 동적로드하는 효과.
import Subject from "./components/Subject";
import Content from "./components/Content";
import Article from "./components/Article";
import Controls from "./components/Controls";
import CreateForm from "./components/CreateForm"
import UpdateForm from "./components/UpdateForm"
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      subject: { title: "WEB", desc: "world wide web!" },
      mode: "welcome",
      selected0,
      contents: [
        { id: 0, title: "HTML", desc: "HyperText Management Language" },
        { id: 1, title: "CSS", desc: "씨에스에스" },
        { id: 2, title: "javascript", desc: "자바스크립트" }
      ]
    
    };
  }
 
  getContent() {
 
    var _mode=this.state.mode;
    if (_mode === "read") {
      var article = this.state.contents[this.state.selected];
      return <Article article={article}></Article>;
    } else if (_mode === "welcome") {
      return <Article article={this.state.subject}></Article>;
    } else if(_mode==="create"){
      return <CreateForm addContent={this.addContent.bind(this)}></CreateForm>;
    } else if(_mode==="update"){
      return <UpdateForm data={this.state.contents[this.state.selected]} updateContent={this.updateContent.bind(this)}></UpdateForm>;
    }
  }
  addContent(title,desc){
    var len=this.state.contents.length;
    var newContents=Array.from(this.state.contents);
    newContents.push({id:len,title:title,desc:desc});
    this.setState({
      contents:newContents,
      mode:'read',
      selected:len
    })
  }
  updateContent(id,title,desc){
    var newContents=this.state.contents;
    newContents[id].title=title;
    newContents[id].desc=desc;
    this.setState({
      contents:newContents,
      mode:'read',
      selected:id
    });
  }
  changeMode(mode){
    this.setState({
      mode:mode
    });
  }
 
  changeArticle(i) {
    this.setState({
      mode:'read',
      selected: i
    });
  }
  render() {
    return (
      <div>
        <Subject
          title={this.state.subject.title}
          sub={this.state.subject.sub}
          onClicked={this.changeMode.bind(this)}
        ></Subject>
        <Content
          contents={this.state.contents}
          onClicked={this.changeArticle.bind(this)}
        ></Content>
        <Controls
          controls={this.state.controls} onClicked={this.changeMode.bind(this)}
        ></Controls>
        {this.getContent()}
      </div>
    );
  }
}
export default App;
 
cs

Content 컴포넌트를 사용할때, chageArticle 메서드를 넘겨준다.

이 때 bind를 해주는 이유는

자바스크립트에서 this키워드는 해당 객체를 나타내는게 아니라 어디서 호출되는가를 나타낸다.
changeArticle 메서드는 전역객체에서 호출되기 때문에 함수 내 코드에 this.setState의 this는 전역객체를 가리키게 된다.

당연히 전역객체에 state가 없기 때문에 오류가 난다.

이 메서드를 누가 호출 하는것 인가를 지정해줘야 한다.

bind(this)를 해주면 이 메서드는 호출될때 App컴포넌트 객체에서 호출된다는 뜻이 되어서

this.setState를 할 때 애가 App컴포넌트객체라고 생각하고 작동한다.

 

this랑 bind에 대한 개념은 이 형님이 잘 정리해 놓으셨다.

https://blueshw.github.io/2018/03/12/this/

 

https://blueshw.github.io/2018/03/12/this/

 

blueshw.github.io

 

<Content.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React, { Component } from "react";
import { tsConstructorType } from "@babel/types";
class Content extends Component {
  constructor(props) {
    super(props);
    
  }
  changePage(e){
    e.preventDefault();
    this.props.onClicked(e.target.dataset.id);
    
  }
  render() {
    var list = [];
    var data=this.props.contents;
    var i=0;
    while(i<data.length){
      var li=<li><a href='#' data-id={data[i].id} onClick={this.changePage.bind(this)}>{data[i].title}</a></li>
      list.push(li);
      ++i;
    }
    return (
      <nav>
        <ul>{list}</ul>
      </nav>
    );
  }
}
 
export default Content;
 
cs

자식 컴포넌트에서는 a태그를 쫙 깔아주는데

onClick=핸들링함수 일케 해주면 이벤트가 알아서 해당 함수의 인자로 전달된다.

changePage함수가 실행되고 이 때도 마찬가지로 바인딩을 해줘야 changePage 내부의 this키워드를 제대로 사용할 수 있다.

 

e.preventDefault()로 a태그가 기본적으로 수행하는 이벤트처리를 막아주고

this.props.onClicked()를 호출한다. 즉 App컴포넌트에서 넘어온 핸들링 함수를 수행한다.

html5부터 추가됐다던가 뭐던가 하튼간 태그에 data-로 시작하는 속성을 달아주면

dataset안에 속성명으로 속성들이 생긴다.

data-id={} 이런식으로 id값들을 세팅해줬기 때문에 이제 a태그의 dataset속성 안에 id값들이 배정된다.

e.target으로 이벤트가 발생된 a태그를 찾아내고 dataset에 id를 찾아내서

App컴포넌트에서 props로 넘어온 함수에 인자로 넘긴다.

 

그럼 App컴포넌트에선 클릭된 놈의 내용을 맨 밑에 띄워준다.

onClicked말고도 값이 변경될때마다 냄새를 맡는 onChange도 있고

form에서는 onSubmit 쓰면된다.

 

<UpdateForm.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import React, { Component } from "react";
class UpdateForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      id: props.data.id,
      title: props.data.title,
      desc: props.data.desc
      
    };
    this.changeHandler=this.changeHandler.bind(this);
  }
  changeHandler(e){
      this.setState({[e.target.name]:e.target.value});
      //javascript 신종문법!
      //if e.target.name==='title'이면 title:바꿔야하고 이런거 대신에 []로 처리해주면땡
  }
  render() {
    return (
      <div>
        <form
          action="#"
          method="post"
          onSubmit={function(e) {
            e.preventDefault();
 
            var title = e.target.title.value;
            var desc = e.target.desc.value;
            this.props.updateContent(this.props.data.id, title, desc);
          }.bind(this)}
        >
          <input
            name="title"
            value={this.state.title}
            placeholder="title"
            onChange={this.changeHandler}
          ></input>
          <input
            name="desc"
            value={this.state.desc}
            placeholder="desc"
            onChange={this.changeHandler}
          ></input>
          <input type="submit"></input>
        </form>
      </div>
    );
  }
}
 
export default UpdateForm;
//그냥 input으로 놓으면 값이 변경이안된다
/* 따라서 자신의 state에 title,desc를 세팅해놓고 input에서 이벤트가 발생할때마다 (onChange=)
state의 title,desc가 바뀌게끔 해줘야한다. 그러면 자동으로 input의 value도 바뀐값을 참조하게되므로 input에 있는 값이 바뀐다.
이때 굳이 props로 넘어온걸 state에 할당해서 바꿔주는이유는, props는 R/O이기 때문이다.
*/
 
cs

내용을 업데이트 해주는 form이다.

' > 리액트' 카테고리의 다른 글

[리액트]형상관리  (0) 2019.08.31
[리액트]앱 빌드/배포  (0) 2019.08.31
[리액트]props state  (0) 2019.08.31
[리액트]컴포넌트  (0) 2019.08.31
[리액트]플젝 만들기  (0) 2019.08.31

1. props

props는 생성자 인자로 비유해서 이해했다.

MyComponent 태그를 보면 속성=값 으로 인자를 넘겨줬다.

객체를 찍어낼때 생성자 인자로 "a", "b"를 넘겨줬다고 생각하면된다.

2.state

state는 클래스의 private 멤버로 비유해서 이해했다.

state를 정의하려면 위와 같이 하면 된다.
생성자 써주고 그 안에다 정의해주면 된다. 걍 방식이다.

제품으로 치면 props는 외부 연결선이고 state는 내부 전선에 해당한다.

내부 전선이 밖으로 나와있으면 좋은제품이라할수없다.

위와 같이 구현하면 <App/>을 렌더링하는 입장에서는 state가 있는지 없는지 모른다.

즉 외부에선 모른다.

 

<응용1>

props로 넘어온 애들을 state에 세팅해주고 사용할 때는 위와 같이

constructor만들고 그안에서 this.state=해서 세팅해주면된다.

 

<응용2>

컴포넌트 안에 내부 컴포넌트가 있을때, 자신의 state를 내부 컴포넌트의 props로 계층화해서 내려줄 수 있다.

 

3. 개꿀

class안의 state, props가 변하면 render가 자동으로 재호출되고 하위 컴포넌트의 render도 싹다 호출된다고 한다.
하나가 변경됐을 때, 그에 영향을 받는 하위 애들이 알아서 갱신되니까 편하다.
실제로 각 컴포넌트 render() 함수 가서 console.log찍어보면 알 수 있다.

 

<주의할점>

state가 바뀌면 그 state를 참조하는 모든 자식컴포넌트들이 다시 render되는데,
이때 this.state.a=b 일케 변경시키면 값은 바뀌지만 render가 안된다.
this.setState({ a:b });
일케 해줘야 다시 render가 된다.


내가 처음생각한건 private변수라 setter 메쏘드를 통해서만 접근이되는줄알았는데

그건 아니고 setter 안에 render를 다시하게끔 내부구현이 되어있는듯 싶다.

' > 리액트' 카테고리의 다른 글

[리액트]형상관리  (0) 2019.08.31
[리액트]앱 빌드/배포  (0) 2019.08.31
[리액트]이벤트 핸들러  (0) 2019.08.31
[리액트]컴포넌트  (0) 2019.08.31
[리액트]플젝 만들기  (0) 2019.08.31

리액트의 컴포넌트는 걍 나만의 태그를 만드는 것이라 생각하면 쉽다.

<div>, <p> 이런거는 원래 html기본 태그고

<Content> <Controls>처럼 내맘대로 이름지어서 태그를 쓸수있다.

클래스로 만들고 클래스이름.js로 만든다.

 

<Article.js>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React, { Component } from "react";
class Article extends Component {
  render() {
    
    return (
      <div>
        <h3>{this.props.article.title}</h3>
 
        <p>{this.props.article.desc}</p>
      </div>
    );
  }
}
 
export default Article;
 
cs
 

Component 클래스를 상속받아서 만들어야하고

render함수에 이 컴포넌트가 어떤내용을 보여줄지 기술한다.

여러개의 태그가 병렬로 있으면 금마들을 아우르는 태그가 꼭 있어야된다. 걍 리액트 문법이다.

위같은경우 <h3>태그랑 <p>태그가 병렬로 있어서 <div>로 감싸줬다.

플젝 만들면 생기는 App.js도 컴포넌트다.

다른 데에서 사용하려면 export를 해주고

쓰고자하는 파일에서 import를 해주면된다.

 

화살표 따라가기

index.js를 따보면 index.html에 있는 div를 id로 끍어와서 거기에 <App>태그를 렌더링하는걸 볼수있다.

App.js를 따보면 App컴포넌트의 render()가 있고 그 안에 <Subject> 태그가 있다.
Subject.js를 따보면 Subject컴포넌트의 render()가 있고 안에 내용이 있다.

 

컴포넌트를 클래스로 태그를 객체로 이해하면 쉽다.

 

' > 리액트' 카테고리의 다른 글

[리액트]형상관리  (0) 2019.08.31
[리액트]앱 빌드/배포  (0) 2019.08.31
[리액트]이벤트 핸들러  (0) 2019.08.31
[리액트]props state  (0) 2019.08.31
[리액트]플젝 만들기  (0) 2019.08.31

갓 생활코딩형님의 리액트 입문 수업이 있어서 공부했다.

https://www.opentutorials.org/module/4058

 

React

수업소개 리액트 입문 수업입니다. 이 수업에서는 아래와 같은 내용을 다루고 있습니다.  리액트를 사용하는 이유 리액트의 컴포넌트를 만드는 법 리액트와 불변(immutable)의 관계 아래 내용은 다루고 있지 않습니다.  데이터베이스 서버와 연동 redux 수업대상 리액트를 통해서 재사용 가능한 사용자 정의 태그(컴포넌트)를 만들고 싶은 분, single page application을 구현하고 싶은 분 수업을 보는 다른 방법 Youtube 재생목록 수업에

www.opentutorials.org

리액트도 express처럼 플젝 기본 골격을 제공해주는게 있다.

 

nodejs 깔고 npm으로 create-react-app 설치하고
create-react-app
directory_name 해주면

 

해당 디렉명으로 리액트 프로젝트가 설치된다.
어차피 실제 화면에 뿌려질 내용들은 api서버를 따로만들어 읽어오면 되기 때문에

프론트엔드를 관리하는 서버를 만드는 것이다.
나중에 api서버를 구축해서 두 서버를 같이 켜주면 된다.

 

' > 리액트' 카테고리의 다른 글

[리액트]형상관리  (0) 2019.08.31
[리액트]앱 빌드/배포  (0) 2019.08.31
[리액트]이벤트 핸들러  (0) 2019.08.31
[리액트]props state  (0) 2019.08.31
[리액트]컴포넌트  (0) 2019.08.31

+ Recent posts