제공되는 강의는 끝까지 들으며 기본적인 react에 대한 내용은 이해된것 같다
react에는 클래스형과 함수형 두가지로 구분되는데, 함수형이 나중에 나온것이며 제공되는 기능이 적었으나 hook이라는 개념으로 그 이상의 기능을 한다고한다. 그래서 지금 프로젝트가 함수형으로 작성되었나보다
강의 들으며 따라한 결과물로 완성된 화면은
기본적인 CRUD를 구성한건데, 컴포넌트화해서 최대한 react 스럽게 따라해보았다
소스 구조로는
App
Subject
TOC
Control7
가 있고 Control 아래로
ReadContent / CreateContent / UpdateContent
으로 있다
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;
this.state = {
mode:'welcome',
selected_content_id:2,
subject:{title: 'WEB', sub: 'world wide web!'},
welcome:{title: 'Welcome', desc: 'Hello, React!!!'},
contents:[
{id:1, title:'HTML', desc:'HTML is Hyper ...'},
{id:2, title:'CSS', desc:'Csssss'},
{id:3, title:'JavaScript', desc:'Javaaaaa'},
]
};
}
getReadContent(){
var i = 0;
while(i < this.state.contents.length){
var data = this.state.contents[i];
if(data.id === this.state.selected_content_id){
return data;
}
i = i + 1;
}
}
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} desc={_desc}></ReadContent>
} else if(this.state.mode === 'read'){
var _content = this.getReadContent();
_article = <ReadContent title={_content.title} desc={_content.desc}></ReadContent>
} else if(this.state.mode === 'create'){
_article = <CreateContent onSubmit={function(_title, _desc){
//변수로 title, desc를 입력받으면 content에 추가
this.max_content_id = this.max_content_id + 1;
//push는 본래값을 바꾸지만 concat은 새로만드는것
var _content = this.state.contents.concat(
{id:this.max_content_id,title:_title, desc:_desc}
);
this.setState({
contents: _content,
mode:'read',
selected_content_id: this.max_content_id
});
}.bind(this)}></CreateContent>
} else if(this.state.mode === 'update'){
var _content = this.getReadContent();
_article = <UpdateContent data={_content} onSubmit={
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;
}
this.setState({
contents:_contents,
mode:'read'
});
}.bind(this)}></UpdateContent>
}
return _article;
}
render() {
console.log('App 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){
if(_mode === 'delete'){
if(window.confirm('Really?')){
var _contents = Array.from(this.state.contents);
var i = 0;
var deletedTitle = '';
while(i < _contents.length){
if(_contents[i].id === this.state.selected_content_id){
deletedTitle = _contents[i].title;
_contents.splice(i, 1);
break;
}
i = i + 1;
}
this.setState({
mode:'welcome',
contents:_contents
});
alert('Deleted : ' + deletedTitle);
}
} else{
this.setState({
mode:_mode
})
}
}.bind(this)}></Control>
{this.getContent()}
</div>
);
}
}
export default App;
App.js
DB가 없어서 constructor에서 state에 현재 뿌려줄 데이터를 임의로 저장해놓고 이 데이터를 현재 component에서 쓰거나 props로 넘기거나
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function(){
this.setState({mode:'welcome'});
}.bind(this)}>
</Subject>
subject의 컴포넌트로 title, sub, onChangePage를 props로 넘김(사실 onChangePage도 넘긴다는게 맞는 표현인지는 모르겠다)
이렇게 되면 상위 컴포넌트인 App에서 사용하는 값을 Subject 컴포넌트로 넘겨서 사용할 수 있게 만듦
this.props.title
<header>
<h1><a href="/" onClick={function(e){
e.preventDefault();
this.props.onChangePage();
}.bind(this)}>{this.props.title}</a></h1>
{this.props.sub}
</header>
1번의 경우는 'props로 넘긴다'라는 표현을 쓰는데, 2번의 경우는 어떻게 표현하는지 모르겠다
하위 컴포넌트인 Control 컴포넌트는
<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>
이렇게 생겼는데, 중간에
this.props.onChangeMode('update');
이런 부분이 있다. 넘겨받은 props의 'onChangeMode'라는 함수(?)에 어떠한 값을 넣어주는데
<Control onChangeMode={function(_mode){
if(_mode === 'delete'){
if(window.confirm('Really?')){
var _contents = Array.from(this.state.contents);
var i = 0;
var deletedTitle = '';
while(i < _contents.length){
if(_contents[i].id === this.state.selected_content_id){
deletedTitle = _contents[i].title;
_contents.splice(i, 1);
break;
}
i = i + 1;
}
this.setState({
mode:'welcome',
contents:_contents
});
alert('Deleted : ' + deletedTitle);
}
} else{
this.setState({
mode:_mode
})
}
}.bind(this)}>
</Control>
첫줄에
function(_mode){
이 부분에서 _mode 가 하위 컴포넌트에서 받아온 'create'와 같은 값이 되는것
하단에
else{
this.setState({
mode:_mode
})
이렇게 함으로써 현재 mode를 setState를 통해 변경해서 하위 컴포넌트로부터 값을 받을 수 있다
React의 기본적인 개념과 javascript를 전혀 몰랐지만, 이제는 읽고 쓰는것 정도는 가능해진 것 같다
기본적인 내용을 담고있는 강의, 소스니 종종 잊을때 마다 봐줄 필요가 있겠다
혹시 몰라서 메모