피드로 돌아가기
새로워지기·서른의 생활코딩

[생활코딩 따라가기] REACT, 대망의 CRUD~ 중, create

NS
normalstory
표지 이미지
YouTube 영상 미리보기YouTube
외부 미디어
YouTube 영상 미리보기YouTube
외부 미디어
YouTube 영상 미리보기YouTube
외부 미디어

영상 요약

  1. 요약이 아직 없습니다.

  2. 요약이 아직 없습니다.

https://www.youtube.com/watch?v=nwwJ2xU7E8w&list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi&index=28

 

 

1. Create

1. CRUD별 state.mode 값을 변경하기 

1) 일단 CUD목록을 만들자 

import React, {Component} from 'react';
import './App.css';

import Subject from "./component/Subject"
import TOC from "./component/TOC"
import Content from "./component/Content"


class App extends Component{
  constructor(props){ 
    super(props); 
    this.state={
      mode :"read", 
      welcome : {title:'welcome', desc:'hello react'},

      selected_content_id : 1,

      subject:{title:'WEB', sub:'world wide web !'},
      content:[
        {id:1, title:"HTML", desc:"HTML is HyperText "},
        {id:2, title:"CSS", desc:"Css is for design "},
        {id:3, title:"JS", desc:"javascript is for intrective "}
      ]
    }
  }

  render(){
    console.log('APP render & this is : ' , this);
    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.content.length){
        var data = this.state.content[i];
        if(data.id === this.state.selected_content_id){
          _title=data.title;
          _desc=data.desc;
          break;
        }
        i++; 
      }
    }
    
    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 data={this.state.content}
          onChangePage={function(id){
            this.setState({
              mode : 'read',
              selected_content_id : Number(id)
            })
          }.bind(this)}
         ></TOC>

          <ul>
           <li><a href="/create" >create</a></li>
           <li><a href="/update" >update</a></li>
           <li><input type="button" value="delete"></input></li>
         </ul>

         <Content title={_title} desc={_desc}></Content>
      </div>
    );
  }
}
export default App;

2) CUD 목록을 컴포넌트로 변경

(1) Control.js

import React, {Component} from 'react';

class Control extends Component{
    render(){
      console.log('control render');
      return(
        <ul>
          <li><a href="/create" >create</a></li>
          <li><a href="/update" >update</a></li>
          <li><input type="button" value="delete"></input></li>
        </ul>
      );
    }
  }

  export default Control;

(2) app.js

 - 맨위에 

import Control from "./component/Control"

 - <ul>...</ul> 있던 자리에 아래 코드 추가

<Control></Control>

 

3) 클릭할 때마다 모드변경 

앞서 실습한 TOC 또는 WRB 클릭 시 mode를 변경했던 방법과 동일하게 진해하면 되는거 같다 

* 깜박해서 삽질한 기억 : 양쪽 모두 .bind(this) 해줘야 한다는거~ ㅋ

app.js  - 의 <Control> </Control> 부분에 사용자정의 이벤트 설정하고 

<Control onChangeMode={function(_mode){
  this.setState({
  	mode:_mode
  })
}.bind(this)}></Control>

control.js - 여기서 앞에 설정한 이벤트 가져가 쓰고 

import React, {Component} from 'react';

class Control extends Component{
    render(){
      console.log('control render');
      return(
        <ul>
          <li><a href="/create" onClick={function(e){
            e.preventDefault();
            this.props.onChangeMode("create");
          }.bind(this)}>create</a></li>
          <li><a href="/update" onClick={function(e){
            e.preventDefault();
            this.props.onChangeMode("update");
          }.bind(this)}>update</a></li>
          <li><input type="button" onClick={function(e){
            e.preventDefault();
            this.props.onChangeMode("delete");
          }.bind(this)} value="delete"></input></li>
        </ul>
      );
    }
  }

  export default Control;

4) 새로운 컴포넌트 생성 및 조정

(1) 기존의 <Content> 영역이, mode가 read일 때와 create 일때를 구분하여 출력되도록 코드 조정

 <Content> </Content> 자리를 

{_content}로 바꾸고 

-  render(){ ...여기... return(); }   

//'여기'에, {_content}에 대한 조건문(만약 모드가 create 라면~) 추가

 (앞략)
 render(){
    console.log('APP render & this is : ' , this);
    var _title, _desc,_content = null;
    if(this.state.mode === 'welcome'){
      _title=this.state.welcome.title;
      _desc=this.state.welcome.desc;
      _content = <Read_Content title={_title} desc={_desc}></Read_Content>
    }else if(this.state.mode === 'read'){
      var i =0;
      while(i<this.state.content.length){
        var data = this.state.content[i];
        if(data.id === this.state.selected_content_id){
          _title=data.title;
          _desc=data.desc;
          break;
        }
        i++; 
      }
      _content = <Read_Content title={_title} desc={_desc}></Read_Content>
    }else if(this.state.mode === 'create'){
      _content = <Create_Content></Create_Content>
    }
    
    return ( ... 중략 ...);
 }
 (말략 ㅋ)

- Create_Content.js - '폼 태그' 추가, 'submit 클릭시 얼럿 테스트'까지 한.

참고로 onSubmit는 순수 html 스펙, 그 안에{function(){}} 내용은 리액트 스펙
import React, {Component} from 'react';

class Create_Content extends Component{
    render(){
      console.log('Create render');
      return(
        <article>
          <h2>Create</h2>

          <form action="/create_process" method="post" 
            onSubmit={function(e){
              e.preventDefault();
              alert("submit");
            }.bind(this)}
          >
            <p><input type="text" name="title" placeholder="title"></input></p>
            <p><textarea name="desc" placeholder="description"></textarea></p>
            <p><input type="submit"></input></p>
          </form>
        </article>
      );
    }
  }
  export default Create_Content;

e.preventDefault(); 했으니까, 얼럿창의 '확인' 버튼을 눌러고 페이지가 리로드되지 않고 얌전히 있으면 성공. 

(2) 이젠, submit 하면, create 된 내용을 TOC 목록에 추가 ~

e.targrt이 form 자체를 가르킨다 
- 얼럿 코드 아래 debugger; 를 작성하고 새로고침해서 e.targrt의 상세 속성을 확인해볼 수 있다. 

- 일단 값 던지기

app.js

앞서 만든<Create_Content></Create_Content> 컴포넌트 안에 사용자정의 이벤트 onSubmit={}을 추가해 값을 받을 준비를 한다.

 

_content = <Create_Content onSubmit={function(_title, _desc){
  console.log(_title, _desc)
}.bind(this)}></Create_Content>

Create_Content.js 

form 태그 안에 있는 값들을 사용자정의 이벤트 onSubmit(제목, 내용)의 인자로 담아 app.js로 전달한다.

//debugger;
this.props.onSubmit(e.target.title.value, e.target.desc.value);

- 이번엔 UI 목록에 추가 

app.js

(---초략)
//*** 여긴 constructor(props){ ...여기(바로뒤에);  this.state={..} }

//1) contents의 수를 담은 변수를 추가하기(ui와 상관없으니, state 밖에 선언)
this.count_contents_id=3;

(---중략)

//*** 여긴 <Create_Content onSubmit={function(){ ...여기~... }}> 
//1) contents 맨뒤에 넣기 위해 +1 
this.count_contents_id=this.count_contents_id+1;
 
//2) 추가하기 - 아직 리액트는 모른다. 
this.state.content.push({
	id:this.count_contents_id, title:_title, desc:_desc
});

//3) 이제 리액트도 안다.
this.setState({
	content: this.state.content
});

(---말략)

- 하지만, 다시.      app.js 

다른 방식의 create - push VS concat 
- state에 값을 변경하는 경우 원본을 변경하지 않고 새로운 데이터를 넣는 concat를 추천한다
- 추후 성능개선 이슈 등에 더 유리하다 고 한다. 
import React, {Component} from 'react';
import './App.css';

import Subject from "./component/Subject"
import TOC from "./component/TOC"
import Control from "./component/Control"
import Read_Content from "./component/Read_Content"
import Create_Content from "./component/Create_Content"


class App extends Component{
  constructor(props){ 
    super(props); 

    this.count_contents_id=3;

    this.state={
      mode :"create", 
      welcome : {title:'welcome', desc:'hello react'},

      selected_content_id : 1,

      subject:{title:'WEB', sub:'world wide web !'},
      content:[
        {id:1, title:"HTML", desc:"HTML is HyperText "},
        {id:2, title:"CSS", desc:"Css is for design "},
        {id:3, title:"JS", desc:"javascript is for intrective "}
      ]
    }
  }

  render(){
    console.log('APP render & this is : ' , this);
    var _title, _desc,_content = null;
    if(this.state.mode === 'welcome'){
      _title=this.state.welcome.title;
      _desc=this.state.welcome.desc;
      _content = <Read_Content title={_title} desc={_desc}></Read_Content>
    }else if(this.state.mode === 'read'){
      var i =0;
      while(i<this.state.content.length){
        var data = this.state.content[i];
        if(data.id === this.state.selected_content_id){
          _title=data.title;
          _desc=data.desc;
          break;
        }
        i++; 
      }
      _content = <Read_Content title={_title} desc={_desc}></Read_Content>
    }else if(this.state.mode === 'create'){
      _content = <Create_Content onSubmit={function(_title, _desc){
        //1
        this.count_contents_id=this.count_contents_id+1;

        //2-1
        // this.state.content.push({
        //   id:this.count_contents_id, title:_title, desc:_desc
        // });
        // this.setState({
        //   content: this.state.content
        // });

        //2-2
        var _new_content = this.state.content.concat({
          id:this.count_contents_id, title:_title, desc:_desc
        });
        this.setState({
          content: _new_content
        });

      }.bind(this)}></Create_Content>
    }
    
    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 data={this.state.content}
          onChangePage={function(id){
            this.setState({
              mode : 'read',
              selected_content_id : Number(id)
            })
          }.bind(this)}
         ></TOC>
        <Control onChangeMode={function(_mode){
          this.setState({
            mode:_mode
          })
        }.bind(this)}></Control>
        {_content}
      </div>
    );
  }
}
export default App;

결과는 위와 동일~ 

 

1+a. 

1) push VS concat 

 

    (1) 원본을 바로 수정하지 않고, 복제본을 만들어서 수정한다. 

    (2) push는 shouldComponentUpdate를 사용 할 수 없다.

 

2) shouldComponentUpdate(newPros, newState)

     (1) TOC가 화면에 표시되기 위해서는 this.state.content[]이 반영되는데 

         - content[]의 내용이 바뀌지 않았을 때는 content[]의 render()가 실행될 필요가 없지만 계속 실행되고 있다.

     (2) shouldComponentUpdate(){ return ...} 를 추가하면

         render()보다 먼저 실행된다.

         - return 이 true 이면 모든 render()를 실행하고, false이면 render()를 실행하지 않는다.

         shouldComponentUpdate는 새롭게 바뀐 값과 이전 값에 각각 접근할 수 있다.

         새롭게 바뀐 값과 이전 값에 맞춰 render()의 실행여부를 개발자가 조절할 수 있다.

TOC.js

import React, {Component} from 'react';  

class TOC extends Component{
    shouldComponentUpdate(newProps, newState){
      console.log(" ======> shouldComponentUpdate",
        newProps.data,
        this.props.data
      );
      if(this.props.data === newProps.data){
        return false;
      }
      return true;
    }

    render(){
      console.log(' => TOC render');
      var lists=[];
      var data = this.props.data;
      var i=0;
      while(i<data.length){
        lists.push(<li key={data[i].id}>
          <a href={"/content/"+data[i].id}
            data-skdjfnsdkfj = {data[i].id}

            onClick={function(id,e){
              e.preventDefault();
              this.props.onChangePage(id);
            }.bind(this, data[i].id)}
          > {data[i].title}
          </a> </li>);
        i = i+1;
      }
      return(
        <nav>
          <ul>
            {lists}
          </ul>
        </nav>
      );
    }
  }

  export default TOC;

 

2) immutable 불변성 

      (1) Array의 특징 응용

       불변성에 대한 부분만 고려된다면, shouldComponentUpdate() 없이 push로도 구현할 수 있다. 

//2-1 + immutable 불변성

var _new_content = Array.from(this.state.content);

_new_content.push({
	id:this.count_contents_id, title:_title, desc:_desc
});

this.setState({
	content: _new_content
});

      (2) 객체의 경우,

            but, 혹시나 해서 테스트해봒는데... ㅋ 

      (3) 이렇게 왔다갔다하기 애매한 경우 -> 라이브러리를 활용할 수도 있음!

              모든 명령어들이~ 다~ 원본에 대해 불변하게 되기 때문에 혼란을 줄여줄 수 있다. 

https://github.com/immutable-js/immutable-js

 

immutable-js/immutable-js

Immutable persistent data collections for Javascript which increase efficiency and simplicity. - immutable-js/immutable-js

github.com

 

 

2. Update

https://www.youtube.com/watch?v=YKdebEty6uQ&list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi&index=36

(ing)

 

 

 

친절한 찰쓰씨
글쓴이
친절한 찰쓰씨
친절한 찰쓰씨 · 일상 UX 디자이너
기획·디자인·단상을 조용히 기록합니다.
작가 페이지에서 더 보기

이어서 읽기

새로워지기

꾸준히, 오래, 지치지 않고

Mar 31, 2026·8
새로워지기

테크 라이프 발란스

Feb 7, 2026·3
새로워지기

휴탈리티 박정렬

Feb 7, 2026·11