본문 바로가기

학습노트/React

[React] (11) Update 기능 구현 (CRUD)

  Update기능은 Create기능과 Read기능이 결합된 형태라고 볼 수 있다. 그래서 우선 components폴더 안에 UpdateContent.js를 만든다.

 

UpdateContent.js

import React, { Component } from 'react';

class UpdateContent extends Component {
  render() {
    console.log('UpdateContents render')
    return (
      <article>
        <h2>Update</h2>
        <form action="/create_process" method="post"
        onSubmit={function(e) {
          e.preventDefault();
          // e의 속성 값을 이용해서 e.target.id값 으로 받아온다.
          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"></input></p>
        </form>
     </article>
    );
  }
}

export default UpdateContent;

  위 코드는 CreateContent.js에서 가지고 왔다. 그리고 App.js에 Import 시켜준다.


refactoring (필수아님)

getContent라는 함수를 만들어 조금 정리해준다.

getReadContent라는 함수를 만들어 조금 정리해준다.


 

App.js

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

class App extends Component {
// render 함수보다 먼저 실행이되면서 초기화시켜주고 싶은 것은 constructor안에다가 짜라
// 부모
  constructor(props) {
    super(props);
    this.max_content_id = 3;
    // 초기화 끝내고 state를 초기화 시킨다.
    this.state = {
      mode: "create",
      selected_content_id: 1,
      subject: {title: "Web", sub: "World Wide Web!"},
      welcome: {title:"Welcome", desc:"Hello, React!!!"},
      contents:[
        {id: 1, title: 'HTML', desc: 'HTML is for information'},
        {id: 2, title: 'CSS', desc: 'CSS is for design'},
        {id: 3, title: 'JAVASCRIPT', desc: 'JAVASCRIPT is for interactive'}
      ]
    }
  }
  getReadContent() {
    for(let i = 0; i < this.state.contents.length; i++) {
      let data = this.state.contents[i];
      if(data.id === this.state.selected_content_id) {
        return data;
        break;
      }
    }
  }
  getContent() {
    console.log('App render')
    let _title, _desc, _article = null;
    if(this.state.mode === "welcome") {
      _title = this.state.welcome.title;
      _desc = this.state.welcome.desc;
      _article = <ReadContent title={_title} desc={_desc}></ReadContent>
    } else if(this.state.mode === "read") {
      let _content = this.getReadContent();
      _article = <ReadContent title={ _content.title} desc={ _content.desc}></ReadContent>
    } else if(this.state.mode === "create") {
      _article = <CreateContent onSubmit={function(_title, _desc) {
        this.max_content_id = this.max_content_id + 1;
        let _contents = this.state.contents.concat(
          { id: this.max_content_id, title: _title ,desc: _desc}
        )
        this.setState({
          contents: _contents
        })
        console.log(_title, _desc)
      }.bind(this)}></CreateContent>
    } else if(this.state.mode === "update") {
      let _content = this.getReadContent();
      _article = <UpdateContent data={_content} onSubmit={function(_title, _desc) {
        this.max_content_id = this.max_content_id + 1;
        let _contents = this.state.contents.concat(
          { id: this.max_content_id, title: _title ,desc: _desc}
        )
        this.setState({
          contents: _contents
        })
        console.log(_title, _desc)
      }.bind(this)}></UpdateContent>
    }
    return _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>
      {/* 자식 */}
      <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>
      {this.getContent()}
    </div>
    );
  }
}

export default App;

 

 

UpdataContent.js

import React, { Component } from 'react';

class UpdateContent extends Component {
  render() {
    console.log(this.props.data);
    console.log('UpdateContents render')
    return (
      <article>
        <h2>Update</h2>
        <form action="/create_process" method="post"
        onSubmit={function(e) {
          e.preventDefault();
          // e의 속성 값을 이용해서 e.target.id값 으로 받아온다.
          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"></input></p>
        </form>
     </article>
    );
  }
}

export default UpdateContent;

console.log를 찍어서 update를 누를 때 해당 id값의 data가 잘 넘어오는지 확인한다.

 

css를 누른다.
css를 누른 후 update를 누른다.


 

데이터 가져오기

  form에서 input 태그(또는 textarea태그) value값에 this.props.data.title로 가져오고 싶지만 그것은 데이터 변경이 불가능하다. 왜냐면 props는 read only이기 때문이다. 따라서 새롭게 변형하기 위해 state를 만들어서 변형시킬 수 있는 형태로 만들어준다. 하지만 이것이 다는 아니다. onChange를 활용해서 input에서 변경되는 걸 인지하게 만들어준다. 그리고 setState와 e.target.value 이용해서 바뀌게 만들어준다.

 

 

App.js

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

class App extends Component {
// render 함수보다 먼저 실행이되면서 초기화시켜주고 싶은 것은 constructor안에다가 짜라
// 부모
  constructor(props) {
    super(props);
    this.max_content_id = 3;
    // 초기화 끝내고 state를 초기화 시킨다.
    this.state = {
      mode: "create",
      selected_content_id: 1,
      subject: {title: "Web", sub: "World Wide Web!"},
      welcome: {title:"Welcome", desc:"Hello, React!!!"},
      contents:[
        {id: 1, title: 'HTML', desc: 'HTML is for information'},
        {id: 2, title: 'CSS', desc: 'CSS is for design'},
        {id: 3, title: 'JAVASCRIPT', desc: 'JAVASCRIPT is for interactive'}
      ]
    }
  }
  getReadContent() {
    for(let i = 0; i < this.state.contents.length; i++) {
      let data = this.state.contents[i];
      if(data.id === this.state.selected_content_id) {
        return data;
        break;
      }
    }
  }
  getContent() {
    console.log('App render')
    let _title, _desc, _article = null;
    if(this.state.mode === "welcome") {
      _title = this.state.welcome.title;
      _desc = this.state.welcome.desc;
      _article = <ReadContent title={_title} desc={_desc}></ReadContent>
    } else if(this.state.mode === "read") {
      let _content = this.getReadContent();
      _article = <ReadContent title={ _content.title} desc={ _content.desc}></ReadContent>
    } else if(this.state.mode === "create") {
      _article = <CreateContent onSubmit={function(_title, _desc) {
        this.max_content_id = this.max_content_id + 1;
        let _contents = this.state.contents.concat(
          { id: this.max_content_id, title: _title ,desc: _desc}
        )
        this.setState({
          contents: _contents
        })
        console.log(_title, _desc)
      }.bind(this)}></CreateContent>
    } else if(this.state.mode === "update") {
      let _content = this.getReadContent();
      _article = <UpdateContent data={_content} onSubmit={function(_id, _title, _desc) {
        let _contents = Array.from(this.state.contents);
        for(let i = 0; i < _contents.length; i++) {
          if(_contents[i].id === _id) {
            _contents[i] = {id:_id, title:_title, desc:_desc};
            break;
          }
        }
        this.setState({
          contents: _contents
        });
        console.log(_title, _desc);
      }.bind(this)}></UpdateContent>
    }
    return _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>
      {/* 자식 */}
      <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>
      {this.getContent()}
    </div>
    );
  }
}

export default App;

 

 

UpdateContent.js

import React, { Component } from 'react';

class UpdateContent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      id: this.props.data.id,
      title: this.props.data.title,
      desc: this.props.data.desc
    }
  }
  // inputFormHandler(e) {
  //   this.setState({[e.target.name] :e.target.value})
  // }
  render() {
    console.log(this.props.data);
    console.log('UpdateContents render')
    return (
      <article>
        <h2>Update</h2>
        <form action="/create_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={function(e) {
                      this.setState({title:e.target.value})
                    }.bind(this)}
                    ></input></p>
          <p><textarea name="desc"
                       placeholder="description"
                       value={this.state.desc}
                       onChange={function(e) {
                        this.setState({desc:e.target.value})
                      }.bind(this)}
                       ></textarea></p>
          <p><input type="submit"></input></p>
        </form>
     </article>
    );
  }
}

export default UpdateContent;