Create 구현하기
1. Control 컴포넌트를 작성하고, 이 컴포넌트가 mode를 변경할 수 있도록 onChangeMode props를 추가한다.
// 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');
}.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;
// App.js
...
import Control from './components/Control'
class App extends Component {
...
<Control onChangeMode={function(_mode) {
this.setState({
mode:_mode
});
}.bind(this)}></Control>
...
디버거를 추가하고 create, update, delete를 클릭하면 mode가 변경되는 것을 볼 수 있다.
![]() |
![]() |
2. CreateContent 컴포넌트 추가하기
컴포넌트의 역할이 드러나도록 기존에 가지고 있던 Content.js 파일은 ReadContent.js로 이름을 변경하고, CreateContent.js 파일을 추가해서 Create 기능을 구현하기 위한 폼을 만든다.
그리고 App.js 파일에서 _article 변수를 CreateContent 컴포넌트로 변경해준다.
// CreateContent.js
import { Component } from 'react';
class CreateContent extends Component {
render() {
return (
<article>
<h2>Create</h2>
<form action="create_process" method="post">
<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 CreateContent;
3. input으로 작성된 값 받아오기
CreateContent 컴포넌트에서 onSubmit 함수를 구현하고 입력된 값을 받아온다. App.js 파일에서는 submit함수가 실행될 때마다 contents에 push함수를 사용해서 새로운 값을 추가하도록 작성하는데 현재 contents의 갯수를 참조할 수 있도록 max_content_id 변수를 추가하고 이 값을 이용해서 각 contents의 id를 저장한다.
// CreateContent.js
import { 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)}
>
...
export default CreateContent;
* 배열에 값을 추가할 때 push 함수와 concat 함수를 이용할 수 있다. push 함수는 원본 배열의 값이 바뀌면서 직접 값을 추가하는 반면 concat 함수는 원본 배열은 그대로 두고 값이 추가된 최종 배열을 반환해주기 때문에 리액트에서는 성능 문제로 인해 concat함수를 선호한다. 왜냐하면 원본의 변경으로 인해 render를 다시 호출하게 되면 꼭 필요하지 않아도 화면이 다시 그려져야 하기 때문이다.
// App.js
...
import Control from './components/Control'
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 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'}
]
}
}
...
} else if(this.state.mode === 'create') {
_article = <CreateContent onSubmit={function(_title, _desc) {
this.max_content_id = this.max_content_id+1;
// push 함수를 이용한 방법
this.state.contents.push(
{id:this.max_content_id, title:_title, desc: _desc}
);
this.setState({
contents:this.state.contents
});
// concat 함수를 이용한 방법
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)}></CreateContent>
}
...
* 참고 - 이때 받아올 값을 확인하려면 디버거를 추가한 후 개발자도구 콘솔의 e.target을 출력해서 볼 수 있다.
e.target은 form 자체이고 input 값은 e.target.title.value임을 확인할 수 있다.
Update 구현하기
UpdateContent 컴포넌트를 구현하기 위한 파일을 새로 만들어준다.
인풋이 props를 직접 받아서 바꾸어주면 좋겠지만 props는 읽기전용이기 때문에 constructor에 state를 추가하여 사용해야 하고, 값이 변경되면 setState() 함수를 호출하여 리액트에게 알려주어야 한다.
// UpdateContent.js
import { 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
};
}
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) {
console.log(e.target.value);
this.setState({title: e.target.value});
}.bind(this)}
></input>
</p>
<p>
<textarea
name="desc"
placeholder="description"
onChange={function(e) {
console.log(e.target.value);
this.setState({desc: e.target.value});
}.bind(this)}
></textarea>
</p>
<p>
<input type="submit"></input>
</p>
</form>
</article>
);
}
}
export default UpdateContent;
기존에 있던 App.js 파일의 선택된 컨텐츠의 아이디로 컨텐츠 데이터를 불러오는 부분을 getReadContent함수로 리팩토링해준다.
// App.js
import './App.css';
...
import UpdateContent from './components/UpdateContent';
class App extends Component {
...
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;
...
} 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() {
...
}
}
export default App;
* 참고 - 대괄호를 이용한 인자 전달 : 중복되는 함수를 자바스크립트 최신 문법인 대괄호를 이용해서 리팩토링할 수 있다.
onChange={function(e) {
console.log(e.target.value);
this.setState({title: e.target.value});
}.bind(this)}
inputFormHandler(e) {
this.setState({[e.target.name]:e.target.value});
}
Delete 구현하기
import './App.css';
...
import Control from './components/Control'
class App extends Component {
...
<Control onChangeMode={function(_mode) {
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);
break;
}
i = i + 1;
}
this.setState({
mode: 'welcome',
contents: _contents
});
alert('deleted!');
}
} else {
this.setState({
mode: _mode
});
}
}.bind(this)}></Control>
...
export default App;
'공부하기 > React' 카테고리의 다른 글
Create React App 4주차 - 클래스 & 함수 타입 컴포넌트와 라이프사이클 (2) | 2022.07.14 |
---|---|
Create React App 실행해보기 - 2주차 (0) | 2022.06.15 |
Create React App 실행해보기 - 1주차 (1) | 2022.06.02 |