프론트엔드/react(생활코딩)

Create만들기 (전체 정리)

김마드 2020. 2. 10. 18:09

 

App.js

Create 기능 뿐만 아니라, 전체적으로 복습 겸 아래 흐름을 되짚어 보자.

 

■ this.max_content_id = 3 의 의미는, 그 밑에 create를 통해 content id 를 1개씩 추가해주기 위해, 초기 값을 정해준 것이다. (이 때, 초기값 3은 id this.state.contents의 마지막 id값이 3이기 때문.

 

이를 state안에 두지 않는 이유는, ui 와 전혀 상관없는 로직이기 때문에 밖에다 둔 것이다. (안에 두어도 되긴 하지만, 불필요함 / 성능 저하 

 

■ 컴포넌트는 총 5개로 구성 되어 있다.

 

1) Subject

2) TOC

3) Contol

4) ReadContent

5) CreateContent

 

각 각의 컴포넌트에 대해서 아래 하나씩 살펴보자.

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


class App extends Component {
  constructor(props) {
    super(props);
    this.max_content_id = 3;
    this.state = {
      mode: 'read',
      selected_content_id: 2,
      subject: { title: 'WEB', sub: 'World Wid 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' }
      ]
    }
  }
  render() {
    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>
    } 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;
      }
      _article = <ReadContent title={_title} desc={_desc}></ReadContent>
    } else if (this.state.mode === 'create') {
      _article = <CreateContent 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
        })
      }.bind(this)}></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>
        {_article}
      </div>
    );
  }
}

export default App;

 

Subject.js 컴포넌트

import React, { Component } from 'react';
class Subject extends Component {
    render() {
        return (
            <header>
                <h1><a href="/" onClick={function (e) {
                    e.preventDefault();
                    this.props.onChangePage();
                }.bind(this)}>{this.props.title}</a></h1>
                {this.props.sub}
            </header>
        );
    }
}

export default Subject;

TOC 컴포넌트

import React, { Component } from 'react';

class TOC extends Component {
    shouldComponentUpdate(newProps, newState) {
        console.log("===>TOC render 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-id={data[i].id}
                    onClick={function (e) {
                        e.preventDefault();
                        this.props.onChangePage(e.target.dataset.id)
                    }.bind(this)}
                >{data[i].title}</a></li>);
            i = i + 1;
        }
        return (
            <nav>
                <ul>
                    {lists}
                </ul>
            </nav>
        );
    }
}

export default TOC;

Control 컴포넌트

import React, { Component } from 'react';
class Control extends Component {
    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 onClick={function (e) {
                    e.preventDefault();
                    this.props.onChangeMode('delete');
                }.bind(this)}
                    type="button" value="delete"></input></li>
            </ul>
        );
    }
}

export default Control;

 

ReadContent 컴포넌트

 

import React, { Component } from 'react';

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

export default ReadContent;

CreateContent 컴포넌트

import React, { Component } from 'react';

class CreateContent extends Component {
    render() {
        return (
            <article>
                <h2>Create</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>
                        <input type="text" name="desc" placeholder="description"></input>
                    </p>
                    <p>
                        <input type="submit"></input>
                    </p>
                </form>
            </article >
        );
    }
}

export default CreateContent;