[생활코딩 React] ⑤ Create 기능 구현

Glenn·2019년 11월 19일
0

[생활코딩]React

목록 보기
5/6

🎥 생활코딩 YouTube

1. Create 소개

👀 React를 사용해서 어떠한 방식으로 Create 할 것인가?
🖐 정적으로 출력되어있던 메뉴들을 동적으로 추가해보자!

1) mode 변경 기능

" 아래 사진과 같은 controll Button을 생성하여 클릭시 mode 를 변경해주자 "

//App.js <TOC> 태그 아래
<Control onChangeMode={function (_mode) {//받은 값을 setState를 사용하여 mode값 변경
    this.setState({ mode: _mode });
  }.bind(this)}></Control>

//Control.js
class Control extends Component {
 render() {
   return (
     <ul>
       <li><a href="/create" onClick={function(e){
         e.preventDefault();
         this.props.onChangeMode('create');// create 값 넘겨주기
       }.bind(this)}>create</a></li>
       <li><a href="/update" onClick={function(e){
         e.preventDefault();
         this.props.onChangeMode('update');// update 값 넘겨주기
       }.bind(this)}>update</a></li>
       <li><input onClick={function(e){
         e.preventDefault();
         this.props.onChangeMode('delete');// delete 값 넘겨주기
       }.bind(this)} type='button' value='delete'></input></li>
     </ul>
   );
 }
}
  • Li 추가하기
    : 태그 영역을 App.js에 추가하고, Control.js를 생성하여 import
  • Mode 값 넘겨주기
    : li 태그에 onClick 함수를 생성하여 페이지 이동을 막고, mode 값을 넘기자
  • Mode 값 받기
    : App.js의 OnchangeMode내에서 mode값을 변경한다.

2) mode 전환 기능

" mode가 변환됨에 따라서 Content 영역의 내용이 변경되는 코드를 구현해보자 "
👉 이전 Content를 ReadContent로 변경하고, mode가 create일 경우 CreateContent를 출력하는 코드

//App.js
render() {
    var _title, _desc, _article = null;
    if (this.state.mode === 'welcome') {
      _title = this.state.welcome.title;
      _desc = this.state.welcome.desc;//mode가 welcome일 경우 ReadContent를 출력하기 위한 코드
      _article = <ReadContent title={_title} desc={_desc}></ReadContent>;
    } 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.selected_content_id) {
          _title = data.title;
          _desc = data.desc;
          break;
        }
        i += 1;
      }//mode가 read일 경우 ReadContent를 출력하기 위한 코드
      _article = <ReadContent title={_title} desc={_desc}></ReadContent>;//mode가 create일 경우 CreateContent를 출력하기 위한 코드//상단에서 CreateContent를 import 해야함!!
    } else if (this.state.mode === 'create') {
      _article = <CreateContent></CreateContent>;
    }
    return (
      <div className="App">
        <Subject
          title={this.state.Subject.title}
          sub={this.state.Subject.sub}
          onChangePage={function () {
            this.setState({ mode: 'welcome' });
          }.bind(this)}>
        </Subject>
        <TOC onChangePage={function (id) {
          this.setState({
            mode: 'read',
            selected_content_id: Number(id)
          });
        }.bind(this)}
          data={this.state.contents}></TOC>
        <Control onChangeMode={function (_mode) {
          this.setState({ mode: _mode });
        }.bind(this)}></Control>//원래 contents 영역이였던 부분을 _article로 변경한다.
        {_article}
      </div>
    );
  }

3) form

" form 내의 내용을 구성한다 "

//CreateContent.js
class CreateContent extends Component {
  render() {
    return (
      <article>
        <h2>Create</h2>
        <form action="/create_process" method="post"
        onSubmit={function(e){//html의 기능
          e.preventDefault();
        }.bind(this)}>
          <p><input type="text" name="title" placeholder="title"></input></p>
          <p><textarea name="desc" placeholder="description"></textarea></p>
          <p><input type="submit" value="submit"></input></p>
        </form>
      </article>
    );
  }
}

4) onSubmit 이벤트

" form에서 입력한 값을 onSubmit 이벤트를 사용하여 App.js로 넘겨준다 "

//CreateContent.js
<form action="/create_process" method="post"
          onSubmit={function (e) {//html의 기능
            e.preventDefault();
            this.props.onSubmit(//값 넘겨줌
              e.target.title.value,
              e.target.desc.value);
          }.bind(this)}>
          <p><input type="text" name="title" placeholder="title"></input></p>
          <p><textarea name="desc" placeholder="description"></textarea></p>
          <p><input type="submit" value="submit"></input></p>
        </form>

//App.js
} else if (this.state.mode === 'create') {
      _article = <CreateContent onSubmit={function(_title,_desc){//값을 받아옴
        this.setState({
          contents:{}
        });
      }.bind(this)}></CreateContent>;
    }

5) contents 변경

  • push() 를 사용하여 변경
    : 근본적인 this.state.contents를 변경하는 것
//App.js
} else if (this.state.mode === 'create') {
_article = <CreateContent onSubmit={function (_title, _desc) {
  this.max_content_id += 1;
   this.state.contents.⭐push⭐(
     { id: this.max_content_id, title: _title, desc: _desc }
   );
  this.setState({
     contents: this.state.contents
    });
  }.bind(this)}></CreateContent>;
}
  • concat() 을 사용하여 변경
    : this.state.contents를 가공한 것을 다른 변수에 담아 사용하는 것
//App.js
} else if (this.state.mode === 'create') {
_article = <CreateContent onSubmit={function (_title, _desc) {
  this.max_content_id += 1;var _contents = this.state.contents.concat(
     { id: this.max_content_id, title: _title, desc: _desc }
    )this.setState({
     contents:  _contents
    });
  }.bind(this)}></CreateContent>;
}

🎶 push() 를 사용한다면 후에 다른 가공을 할 경우 번거로울 수도 있으니 concat() 을 사용하여 가공해 사용하는 방법을 추천

작은 프로그램이라면 push나 conact 아무것이나 사용하여도 상관이 없을 수도 있으나, 나중에 프로그램이 확장하게 된다면 concat 을 사용하는 것이 바람직하다.

6) shouldcomponentUpdate

" push와 concat의 연장선 "
shouldcomponentUpdate : 계속해서 호출되는 TOC의 render() 함수, 이 함수를 재사용하지 않고 변화된 것이 있을 경우에만 render() 함수를 호출시킬 수 있는 함수

//TOC.js
class TOC extends Component {//sholdcomponentUpdate를 사용하면 재호출시에 이곳으로 먼저 도달하게 된다
    shouldComponentUpdate(newProps, newState) { 
        console.log(newProps.data, this.props.data);
        if (this.props.data === newProps.data) {
            return false;//false인 경우 여기서 멈추지만
        } else {
            return true;//true인 경우 다시 한번 실행된다
        }
    }
    render() {
        var list = [];
//~
  • 다음과 같은 코드에서 push와 concat을 사용해본다면, push 는 this.props.data와 newProps.data의 값이 같고, concat 은 this.props.data의 값은 그대로이지만, newProps.data 의 값은 변경된다.

7) immnutable

" 원본을 바꾸지 않고, setState를 사용하는 법! 즉, 원본이 불변한다. "

  • Array()
    : Array.from({복제할 배열})
//example Code

var a=[1,2];
//복제하는 부분
var b=Array.from(a);
//a와 b가 같음에도 다른 배열로 인식(false)
console.log(a,b,a===b);
//a와는 관계가 없는 b라는 배열을 가공할 수 있음
b.push(3);
console.log(a,b,a===b);

=====(Result)=====
VM576:3 (2) [1, 2] (2) [1, 2] false
VM576:5 (2) [1, 2] (3) [1, 2, 3] false
  • Object
    : Object.assign({복제할 객체})
//example Code

var a={name : "glenn"};
//객체를 복제하는 부분
var b=Object.assign({},a);
//배열과 마찬가지로 false
console.log(a,b,a===b);
//a와는 관계없는 b의 name 값 변
b.name="hello JavaScript";
console.log(a,b,a===b);

=====(Result)=====
VM988:3 {name: "glenn"} {name: "glenn"} false
VM988:5 {name: "glenn"} 
				{name: "hello JavaScript"} false
  • 다음과 같이 복제를 하는 방법을 사용한다면 복제 👉 push 👉 가공을 하여도 원본은 변하지 않는다.
//적용 코드 App.js

} else if (this.state.mode === 'create') {
      _article = <CreateContent onSubmit={function (_title, _desc) {
        //add content to this.state.contents
        this.max_content_id += 1;
				//배열 복제
        var newContents = Array.from(this.state.contents);
				//가공
        newContents.push(
          { id: this.max_content_id, title: _title, desc: _desc }
        );
        this.setState({
					//적용
          contents: newContents
        });
      }.bind(this)}></CreateContent>;
    }
profile
Front-end developer

0개의 댓글