본문 바로가기

develop/React

React 3 : CRUD

 

생활코딩 강의 들으면서 주석으로 정리한거

읽어보면서 복기하기 

 

 

App.js

 

import './App.css';
import React, { Component } from 'react';
import TOC from './components/TOC';
import ReadContent from './components/ReadContent';
import Subject from './components/Subject';
import Control from './components/Control';
import CreateContent from './components/CreateContent';
import UpdateContent from './components/UpdateContent';


//App 컴퍼넌트 클래스로 생성
class App extends Component {
  //state 설정 (기본모드 설정)
  constructor(props){
    super(props);
    this.max_content_id = 3;
    this.state = {
      mode:"welcome",
      selected_content_id:2,
      //기본적으로 2번 컨텐츠가 선택되게 함.
      subject:{title:'Web',sub:'World wide web'},
      welcome:{title:'Welcome',desc:'Hello, React.'},
      contents:[
        {id:1, title:'HTML', desc:'HTML is HyperText....'},
        {id:2, title:'CSS', desc:'CSS is Cascading...'},
        {id:3, title:'Javascript', desc:'Javascript is for interactive...'}
      ]
      //state는 생성자랑 비슷한데 초기에 내용을 설정해주는 것. 
      //mode는 read상태, 2번 컨텐츠, contents의 내용 설정을 state로 오브젝트로 설정

    }
    //state값 초기화하려고...
    //실행될 떄 render보다 먼저 실행되면서 그 컴퍼넌트를 초기화시켜주고싶은 코드는
    //constructor안에다가 코드를 작성한다. 
  }
  //컴포넌트를 만드는 코드 app이라는 클래스에 component를 상속
  //Render()라는 메소드 가지고 있음. 
  //함수를 만들어서 리팩토링해줌 -1 
  getReadContent(){
            //모드가 read일 때는
            var i = 0;
            while(i<this.state.contents.length){
              //반복문 실행해서 내용 다 보여주게 함
              var data = this.state.contents[i]; //현재 순번에 해당하는 콘텐츠
              if(data.id === this.state.selected_content_id){
                //아이디와 선택한 콘텐츠의 아이디가 같다면 data를 리턴함
                return data;
                break;
              }
              i = i + 1;
            }
  }
  //함수를 만들어서 리팩토링해줌 -2
  getContent(){
      //여기서 구체화해줌
      var _title, _desc, _article = null;

      if(this.state.mode === 'welcome'){
        //모드가 웰컴일때는
        _title = this.state.welcome.title;
        _desc = this.state.welcome.desc;
        _article = <ReadContent title={_title} sub={_desc}></ReadContent>
        //_article에 넣어줌
        //state에서 welcome 부분 내용 가져옴


      //읽기 모드일 때,
      } else if(this.state.mode === 'read'){
        var _content = this.getReadContent();
        //_content에 함수를 불러옴
        _article = <ReadContent title={_content.title} sub={_content.desc}></ReadContent> 
     
     
      //create 모드일 때,
      } else if (this.state.mode === 'create'){
        //_article에 넣어줌
        _article = <CreateContent onSubmit={function(_title, _desc){
          //setState를 통해 새로운 content값 추가
          this.max_content_id = this.max_content_id + 1;
          // this.state.contents.push(
          //   {id: this.max_content_id, title: _title, desc: _desc}
          //   );
          var _contents = Array.from(this.state.contents);
          _contents.push({id: this.max_content_id, title: _title, desc: _desc});
          this.setState({
            contents:_contents
          });
            //push대신에 concat을 사용하는 것이 바람직함
            //push는 원본 데이터를 변경하지만 concat은 원본을 바꾸지 않고 새로운 데이터를 만들어냄.
          this.setState({
            contents:_contents,
            //원본의 복제본을 setState()로 변경
            mode:'read',
            selected_content_id:this.max_content_id
          });
          console.log(_title,_desc);
        }.bind(this)}></CreateContent>


        //update모드라면..?
      } else if (this.state.mode === 'update'){
        _content = this.getReadContent();
        //getReadContent함수를 불러와 _content에 넣는다.
        var _id = _content.id;
        //_article에 넣어줌
        _article = <UpdateContent data={_content} onSubmit={
          function(_id, _title, _desc){
            var _contents = Array.from(this.state.contents); 
            //this.state.contents를 복제해서 새로운 배열이 만들어짐.
            var i = 0;
            while(i < _contents.length){
              if(_contents[i].id === _id){
                _contents[i] = {id:_id, title:_title, desc:_desc};
                break;
              }
              i = i + 1;
            }
  
          this.setState({
            contents:_contents
          });
          console.log(_title,_desc);
        }.bind(this)}></UpdateContent>
      }
      return _article;
      //_article로 리턴값을 받아옴.
  }
  render(){
  
  return (
    //반환하기
    <div className="App">
      <Subject 
        title={this.state.subject.title} 
        sub={this.state.subject.sub}
        onChangePage={function(){
          this.setState({mode:'welcome'});
        }.bind(this)}
        >
      </Subject>
      {/* <header>
       <h1><a href="/" onClick={function(e){
         e.preventDefault();
        this.setState({
          mode:'welcome'
        });
       }.bind(this)}>{this.state.subject.title}</a></h1>
       {this.state.subject.sub}
      </header> */}
      <TOC onChangePage={function(id){
        this.setState({
        mode:'read',
        selected_content_id: Number(id)
      });
      }.bind(this)}
        data={this.state.contents}></TOC>
      <Control onChangeMode={function(_mode){
        //받아온 인자로 모드를 변경함

        //delete 모드일 때,
        if(_mode === 'delete'){
          if(window.confirm('really?')){
            //삭제할지 확인 여부 물어보는 창
            var _contents = Array.from(this.state.contents);
            var i = 0;
            while(i < _contents.length){
              if(_contents[i].id === this.state.selected_content_id){
                _contents.splice(i,1);
                //삭제해준다 splice(배열 인덱스, 삭제할 갯수?)
                break;
              }
              i = i + 1;
            }
            this.setState({
              mode:'welcome',
              contents:_contents
            })
            //삭제하면 모드를 welcome으로 변경하고 변경된 contents로 변경
          }
        } else {
          this.setState({
            mode:_mode
          });
        }

      }.bind(this)}></Control>
      {this.getContent()}
      {/* 함수 불러옴 */}
    </div>
  ); 
 }
}
export default App;

 

 

Control.js

import { Component } from "react";

class Control extends Component {
    render(){
        return(
            <ul>
                <li><a href="/create" onClick={function(e){
                    e.preventDefault();
                    this.props.onChangeMode('create');
                    //여기서 전달한 인자값 createupdatedeleteapp에 있는 함수에 전달
                }.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" value="button" onClick={function(e){
                    e.preventDefault();
                    this.props.onChangeMode('delete');
                }.bind(this)}></input></li>
            </ul>
        );
    }
}

export default Control;

 

 

CreateContent.js

import { Component } from "react";


class CreateContent extends Component {
    render(){
      return (
        <article>
        <h2>Create</h2>
        
        <form action="/create_process" method="post" 
        //form 태그 입력
        onSubmit={function(e){
          //Onsubmit 함수 입력
          e.preventDefault();
          this.props.onSubmit(
            e.target.title.value, 
            e.target.desc.value
          );
          //입력된 제목과 내용을 받아옴
        }.bind(this)}
        >
          <p><input type="text" name="title" placeholder="title"/></p>
          <p>
            <textarea name="desc" placeholder="description"></textarea>
          </p>
          <p>
            <input type="submit"></input>
          </p>
        </form>
        </article>
      );
    }
  }


  export default CreateContent;

 

UpdateContent.js

import { Component } from "react";


//Update 컴포넌트
class UpdateContent extends Component {
  //state로 id, title, desc값을 설정해줌
  constructor(props){
    super(props);
    this.state = {
      id:this.props.data.id,
      title:this.props.data.title,
      desc:this.props.data.desc
    }
    this.inputFormHandler = this.inputFormHandler.bind(this);
  }
  
  inputFormHandler(e){
    this.setState({[e.target.name]:e.target.value});
  }

    render(){
      console.log(this.props.data);
      console.log('Update content Render');

      return (
        <article>
        <h2>Update</h2>
        <form action="/update_process" method="post" 
        onSubmit={function(e){
          e.preventDefault();
          this.props.onSubmit(
            this.state.id,
            this.state.title, 
            this.state.desc,
          );
        }.bind(this)}
        >
          <input type="hidden" name="id" value={this.state.id}></input>
          <p><input 
            type="text" 
            name="title" 
            placeholder="title"
            value={this.state.title}
            onChange={this.inputFormHandler}/>
            </p>
          <p>
            <textarea name="desc" 
                      placeholder="description" 
                      value={this.state.desc} 
                      onChange={this.inputFormHandler}>
            </textarea>
          </p>
          <p>
            <input type="submit"></input>
          </p>
        </form>
        </article>
      );
    }
  }


  export default UpdateContent;

 

update 부분은 아직 미완성 ..!

 

React 19.7 - shouldComponentUpdate() 관련

TOC부분이 자기가 관련 없는 부분에도 쓸데없이 렌더링 되는 것을 막을 수 있다!

그리고 예전 값과 새로운 값에 접근할 수 있다.

 

근데 이거는 큰 프로그램이라서 성능을 향상시켜야할 이슈가 있다면 해당하는 거고

작은 프로그램이라면 따로 concat을 써 복제본을 만들지 않고 그냥 push로 진행해도 된다.

 

빨리 진도 나가는데 급급하지 말고 하나라도 이해하는 걸 중점적으로 하자 .. 

항상 급하게 하다가 다시 돌아오는게 너무 비효율적임

 

복제할 때 배열은 Array.from을 통해서 복제 가능하고

객체는 Object.assign()을 통해 복제 가능하다

복제된 것들은 내용은 같지만 엄연히 다름.

'develop > React' 카테고리의 다른 글