ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

 

React - 17.1. ์ปดํฌ๋„ŒํŠธ ์ด๋ฒคํŠธ ๋งŒ๋“ค๊ธฐ
    return (
      <div className="App">
        <Subject 
        title = {this.state.subject.title} 
        sub = {this.state.subject.sub}>
        </Subject>
        {</*header>
            <h1><a href ="/" onClick={function(e){
              console.log(e);
              e.preventDefault();
              this.setState({
                mode:'welcome'
              });
              alert('hi');
            }.bind(this)}>{this.state.subject.title}</a></h1>
            {this.state.subject.sub}
          </header>*/}
        <TOC data = {this.state.contents}></TOC>
        <Content title = "HTML" desc = {_desc}></Content>
      </div>
    );

- header ํƒœ๊ทธ๋ฅผ ์ฃผ์„์ฒ˜๋ฆฌํ•˜๊ณ  ์›๋ž˜ ์“ฐ๋˜ ํƒœ๊ทธ ์‚ด๋ฆผ

- ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด onChangePage ์ด๋ฒคํŠธ๋ฅผ ์“ธ ์ˆ˜ ์žˆ์Œ

- a ํƒœ๊ทธ๊ฐ€ ํด๋ฆญ๋˜์—ˆ์„ ๋•Œ ์„ค์น˜ํ•œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด ์คŒ

- ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“œ๋ ค๊ณ  ํ•˜๋Š” Subject ์ปดํฌ๋„ŒํŠธ๋Š” onChangePage ์ด๋ฒคํŠธ๊ฐ€ ์žˆ์–ด์„œ ์ด ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋งํฌ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ด๋ฒคํŠธ์— ์„ค์น˜ํ•œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋ ค๊ณ  ํ•จ

<div className="App">
        <Subject 
          title = {this.state.subject.title} 
          sub = {this.state.subject.sub}
          onChangePage={function(){
            alert('hihihi');
          }.bind(this)}
        >
        </Subject>

- App.js์— ์ถ”๊ฐ€

- onChangePage

 

        <header>
            <h1><a href ="/" onClick={function(e){
              e.preventDefault();
              this.props.onChangePage();
            }.bind(this)}>{this.props.title}</a></h1>
            {this.props.sub}
        </header>

- Subject.js์— ์ถ”๊ฐ€

- ๋งํฌ ํƒœ๊ทธ์— onClick ์†์„ฑ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ  preventDefault๋กœ ํŽ˜์ด์ง€ ๋ฆฌ๋กœ๋“œ๋˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ฌ

- onChangePage ํ•จ์ˆ˜ ์‹คํ–‰

 

- WEB์„ ๋ˆŒ๋ €์„ ๋•Œ ์‹คํ–‰์ด ์ž˜ ๋˜๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

 

    return (
      <div className="App">
        <Subject 
          title = {this.state.subject.title} 
          sub = {this.state.subject.sub}
          onChangePage={function(){
            this.setState({mode:'welcome'});
          }.bind(this)}
        >

- alert ์ค„์„ ์ง€์šฐ๊ณ  mode change ์ถ”๊ฐ€

- WEB์„ ๋ˆ„๋ฅด๋‹ˆ ๋ชจ๋“œ๊ฐ€ ์ž˜ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Œ

 

React - 17.2. ์ปดํฌ๋„ŒํŠธ ์ด๋ฒคํŠธ ๋งŒ๋“ค๊ธฐ

๊ธ€ ๋ชฉ๋ก์„ ํด๋ฆญํ–ˆ์„ ๋•Œ App component์˜ state mode๋ฅผ read๋กœ ๋ฐ”๊พธ๊ณ  ํด๋ฆญํ•œ ๊ฒƒ์— ํ•ด๋‹น๋˜๋Š” ์ปจํ…ํŠธ๊ฐ€ ๋ณธ๋ฌธ์— ์ถœ๋ ฅ๋˜๋„๋ก ํ•จ

 

        <TOC onChangePage={function(){
          this.setState({mode:'read'});
        }.bind(this)} 
        data = {this.state.contents}
        ></TOC>

- App.js TOC ์ˆ˜์ •

 

      while(i < data.length){
        // key ๊ฐ’์„ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ
        lists.push(<li key = {data[i].id}>
            <a 
              href = {"/contents/" + data[i].id}
              onClick={function(e){
                e.preventDefault();
                this.props.onChangePage();
              }.bind(this)}
              > {data[i].title} </a>
          </li>);
        i = i + 1;
      }

- TOC.js ์ˆ˜์ •

 

React - 17.3. ์ปดํฌ๋„ŒํŠธ ์ด๋ฒคํŠธ ๋งŒ๋“ค๊ธฐ
      selected_content_id_2,

- 2๋ฒˆ์ผ ๋•Œ ์‹คํ–‰

  render() {
    console.log('App render');
    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.contents.length){
        var data = this.state.contents[i];
        if(data.id === this.state.selected_content_id){
          _title = data.title;
          _desc = data.desc;
          break;
        }
        i = i + 1;
      }
    }

- while๋ฌธ์œผ๋กœ id๊ฐ€ 2์ผ ๋•Œ title๊ณผ desc์— ๊ฐ’์„ ๋„ฃ์–ด์คŒ

- TOC์—์„œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์šฐ๋ฆฌ๊ฐ€ ํด๋ฆญํ•œ ํ•ญ๋ชฉ์˜ id ๊ฐ’์„ ์ฃผ๋ฉด ๋˜์ง€ ์•Š์„๊นŒ?

 

        <TOC onChangePage={function(id){
          this.setState({
            mode:'read',
            selected_content_id:Number(id)
          });
        }.bind(this)} 
        data = {this.state.contents}
        ></TOC>

- App.js ์—์„œ TOC ๋ณ€๊ฒฝ

 

            <a 
              href = {"/contents/" + data[i].id}
              data-id={data[i].id}
              onClick={function(e){
                e.preventDefault();
                this.props.onChangePage(e.target.dataset.id);
              }.bind(this)}
              > {data[i].title} </a>

- TOC.js์—์„œ onChangePage ๊ฐ’ ๋ณ€๊ฒฝ

 

- HTML, CSS, JavaScript๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ๊ฐ’์ด ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Œ

 

React - 18. ๋ฒ ์ด์Šค ์บ ํ”„

state -> ์ˆ˜์ •ํ•  ๋•Œ set.state๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ

- props : read-only, cannot be modified ์ˆ˜์ • ๋ถˆ๊ฐ€๋Šฅ

state์™€ props๋ฅผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•จ

- ์‚ฌ์žฅ๊ณผ ์ง์› ๊ฐœ๋…์œผ๋กœ ๋น„์œ ํ•˜๋ฉด ์‚ฌ์žฅ -> state, ์ง์› -> props

- ์‚ฌ์žฅ์ด ์ผ ๋ชฉ๋ก์„ ๋งŒ๋“ค๋ฉด ์ง์›์€ ๋ชฉ๋ก์— ์žˆ๋Š” ๊ฒƒ์„ ๊ณจ๋ผ์„œ ์ผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ง์›์ด ์ƒˆ๋กœ์šด ์ผ์„ ํ•˜๋ ค๋ฉด ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์žฅ์—๊ฒŒ ํ—ˆ๋ฝ์„ ๊ตฌํ•ด์•ผ ํ•จ

 

React - 19. create ๊ตฌํ˜„ : ์†Œ๊ฐœ

CRUD : Create Read Update Delete

 

React - 19.2 create ๊ตฌํ—Œ : mode ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

Control.js

import { Component } from 'react';

class Control extends Component {
    render(){
      console.log('Subject 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" value="delete" onClick={function(e){
            e.preventDefault();
            this.props.onChangeMode('delete');
          }.bind(this)}></input></li>
        </ul>
      );
    }
  }

  export default Control;

- Subject.js๋ฅผ ๋ณต์‚ฌํ•ด Control.js ๋งŒ๋“ค๊ธฐ

- create, update, delete ๋ชจ๋“œ ๋งŒ๋“ค๊ธฐ

 

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

- App.js์— ์ถ”๊ฐ€

- ์†์„ฑ ๋ˆ„๋ฅด๋ฉด ๋ชจ๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋„๋ก ํ•จ

 

- ๋ชจ๋“œ๊ฐ€ ์ž˜ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ ํ™•์ธ

 

React - 19.3. create ๊ตฌํ˜„ : mode ์ „ํ™˜ ๊ธฐ๋Šฅ
import { Component } from 'react';

class ReadContent extends Component{
    render(){
      console.log('Content render');
      return(
        <article>
          <h2>{this.props.title}</h2>
          {this.props.desc}
        </article>
      )
    }
  }

  export default ReadContent;

- ReadContent ์ œ์ž‘ํ•˜๊ธฐ

- Content๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ

 

import { Component } from 'react';

class CreateContent extends Component{
    render(){
      console.log('Content render');
      return(
        <article>
          <h2>Create</h2>
          <form>
            
            </form>
        </article>
      )
    }
  }

  export default CreateContent;

- CreateContent ์ œ์ž‘

 

    var _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>
    }

- article์„ ์ถ”๊ฐ€ํ•˜๊ณ , Content๊ฐ€ ์žˆ์—ˆ๋˜ ๊ณณ์— {_article}๋กœ ์ˆ˜์ •

 

- ReadContent๊ฐ€ ์ž˜ ๋ณด์ด๋Š” ๊ฒƒ ํ™•์ธ

 

      _article =  <ReadContent title={_title} desc={_desc}></ReadContent>
    } else if(this.state.mode === 'create'){
      _article = <CreateContent></CreateContent>
    }

- App.js์— ์ฝ”๋“œ ์ถ”๊ฐ€

 

- App mode๊ฐ€ create์ผ ๋•Œ CreateContent๊ฐ€ ๋ณด์ž„

 

React - 19.4. create ๊ตฌํ˜„: form
          <form>
            <p><input type="text" name="title" placeholder="title"></input></p>  
          </form>

- CreateContent.js์—์„œ form ์•ˆ์„ ์ž‘์„ฑ

- placeholder : ํผ ์•ˆ์˜ ๊ฐ’์ด ์•„๋ฌด๊ฒƒ๋„ ์—†์„ ๋•Œ 'title' ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ

 

      mode: 'create',

 - App.js์˜ mode์˜ ๊ธฐ๋ณธ๊ฐ’์„ create๋กœ ์„ค์ •

 

            <p><input type="text" name="title" placeholder="title"></input></p>  
            <p>
              <textarea name="desc" placeholder="descripttion"></textarea>
            </p>
            <p>
              <input type="submit"></input>

- CreateContent ๋‚ด์šฉ ์ถ”๊ฐ€

 

          <form action="/create_process" method="post" onSubmit={function(e){
            e.preventDefault();
            alert('Submit !!');
          }.bind(this)}>

 

- ํŽ˜์ด์ง€ ๋กœ๋”ฉ์ด ๋˜์ง€ ์•Š๊ฒŒ ํ•จ

 

React - 19.5. create ๊ตฌํ˜„: onSubmit ์ด๋ฒคํŠธ
          <form action="/create_process" method="post" onSubmit={function(e){
            e.preventDefault();
            this.props.onSubmit(
              e.target.title.value,
              e.target.desc.value
            );

- CreateContent.js์—์„œ e.target.title.value์™€ e.target.desc.value ์ถ”๊ฐ€

- ํผ์— ๋‚ด์šฉ์„ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ์ฝ˜์†”์—์„œ ์ž…๋ ฅํ•œ ๊ฐ’์ด ๋ณด์ด๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Œ

 

React - 19.6. create ๊ตฌํ˜„: contents ๋ณ€๊ฒฝ
    this.max_content_id = 3;

- App.js์— ์ถ”๊ฐ€

 

        this.max_content_id = this.max_content_id + 1;
        this.state.contents.push(
          {id:this.max_content_id, title:_title, desc:_desc}
        );
        this.setState({
          contents:this.state_contents
        });

- ๋ฆฌ์•กํŠธ์— ๋‚˜์ค‘์— ์„ฑ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ๋•Œ ํž˜๋“ค ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ

- concat : ์›๋ณธ์„ ๋ณ€๊ฒฝํ•œ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์ด ๋ฆฌํ„ด๋จ

- push์™€ ๊ฐ™์€ ์˜ค๋ฆฌ์ง€๋„ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ์“ฐ์ง€ ๋ง๊ณ  concat์„ ์“ธ ๊ฒƒ 

 

        var _contents = this.state.contents.concat(
          {id:this.max_content_id, title:_title, desc:_desc}
        )

- ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ์œ„ํ•ด ์ข‹์€ ๋ฐฉ๋ฒ•

 

React - 19.8. create ๊ตฌํ˜„: immutable

immutable : ์›๋ณธ์ด ๋ถˆ๋ณ€ํ•œ๋‹ค

 

React - 20.1. update ๊ตฌํ˜„
import { Component } from 'react';

class UpdateContent extends Component{
    render(){
      console.log('UpdateContent render');
      return(
        <article>
          <h2>Update</h2>
          <form action="/create_process" method="post" onSubmit={function(e){
            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="descripttion"></textarea>
            </p>
            <p>
              <input type="submit"></input>
            </p>
          </form>
        </article>
      )
    }
  }

  export default UpdateContent;

- UpdateContent.js ์ œ์ž‘

 

    } else if(this.state.mode === 'update'){
      _article = <UpdateContent onSubmit={function(_title, _desc){
        this.max_content_id = this.max_content_id + 1;
        var _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>
    }
    console.log('render', this);

- App.js๋กœ ์ถ”๊ฐ€

 

- update๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ์ž˜ ์ „ํ™˜

 

 

React - 20.2. update ๊ตฌํ˜„ : form

props์˜ ๋ฐ์ดํ„ฐ๋Š” read only๋‹ˆ๊นŒ ์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•จ

UpdateContent.js

value={this.props.data.title}

- ์ˆ˜์ • ๋ถˆ๊ฐ€

 

    constructor(props){
      super(props);
      this.state = {
        title:this.props.data.title
      }
    }

- ์ถ”๊ฐ€ํ•ด๋„ ์ˆ˜์ •์ด ๋˜์ง€ ์•Š์Œ

- input์˜ ๊ฐ’์„ ๋ฐ”๊ฟจ์„ ๋•Œ state์˜ ๊ฐ’๋„ ๋ฐ”๋€Œ๊ฒŒ ํ•ด์•ผ ํ•จ

 

    inputFormHandler(e){
      this.setState({[e.target.name]:e.target.value});
    }

- ํ˜„์žฌ target์˜ ์ด๋ฆ„์„ ์•Œ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ

 

this.inputFormHandler = this.inputFormHandler.bind(this);

- binding์ด ๋œ ๊ฒƒ์œผ๋กœ this๋ฅผ ๋ฐ”๊ฟ”์คŒ

 

onChange={this.inputFormHandler}

- ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค ๋” ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ์คŒ

 

React - 20.3. update ๊ตฌํ˜„ : state ๋ณ€๊ฒฝ
<input type="hidden" name="id" value={this.state.id}></input>

- ์‚ฌ์šฉ์ž ๋ˆˆ์— ๋ณด์ด์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ๊ฒƒ

 

Array.from(this.state.contents);

- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณต์ œํ•œ ์ƒˆ๋กœ์šด Array ๋งŒ๋“ค์–ด์ง

 

        function(_id, _title, _desc){
          var _contents = Array.from(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;
          }

- App.js ์ˆ˜์ •

 

- ์ž˜ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒƒ ํ™•์ธ

 

        this.setState({
          contents:_contents,
          mode: 'read'

- ๊ฐ์ž create, update๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๋‚˜์„œ mode๋ฅผ read๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ์ฝ”๋“œ ์ถ”๊ฐ€

 

- create ์ดํ›„ ์ถ”๊ฐ€ํ•œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ˆˆ์— ๋ฐ”๋กœ ๋ณด์ด๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Œ

 

React - 21.delete ๊ตฌํ˜„
        <Control onChangeMode = {function(_mode){
          if(_mode === 'delete'){
            if(window.confirm('really?')){
              var _contents = Array.from(this.state.contents);
              var i = 0;
              while(i < this.state.contents.length){
                if(_contents[i].id === this.state.selected_content_id){
                  _contents.splice(i, 1);
                  break;
                }
                i = i + 1;
              }
              this.setState({
                mode:'welcome',
                contents:_contents
              })
            }
          } else{
            this.setState({
              mode:_mode
            })
          }
        }.bind(this)}></Control>

- App.js์— ์‚ญ์ œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€

 

- delete ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด really? ๋ผ๋Š” ์ฐฝ์ด ๋œจ๊ณ 

 

- ์‚ญ์ œ๋˜์—ˆ๋‹ค๋Š” ๋ฌธ๊ตฌ

 

- ์ž˜ ์‚ญ์ œ๋˜์—ˆ๊ณ  welcome์œผ๋กœ ๋Œ์•„๊ฐ„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Œ

Comments