CreateContent
컴포넌트 내용을 복사해서 UpdateContent
컴포넌트 파일 생성
App.js
에서 render()
함수 내용이 길어져서 보기 힘들어졌으므로 컨텐츠의 id
값을 통제하는 부분과 컨텐츠 내용을 가져오는 부분을 생성자(constructor()
) 함수 안으로 분리해서 넣기
getReadContent()
getReadContent() {
// while을 이용한 id값 통제
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;
break;
}
i = i + 1;
}
}
getContent()
getContent() {
// 컨텐츠 영역에 표시할 _article도 정의해준다.
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) {
// add content to this.state.contents
this.max_content_id = this.max_content_id + 1;;
// push()를 사용한 원본 배열 변경은 권장하지 않음.
// this.state.contents.push(
// { id: this.max_content_id, title: _title, desc: _desc });
// var _contents = this.state.contents.concat(
// { id: this.max_content_id, title: _title, desc: _desc }
// )
var newContents = Array.from(this.state.contents)
newContents.push({id:this.max_content_id, title:_title, desc:_desc})
this.setState({
// contents: _contents
contents: newContents
})
console.log(_title, _desc);
}.bind(this)}></CreateContent>
} else if(this.state.mode === 'update') {
_content = this.getReadContent();
_article = <UpdateContent data={_content} onSubmit={function(_title, _desc) {
// add content to this.state.contents
this.max_content_id = this.max_content_id + 1;;
// push()를 사용한 원본 배열 변경은 권장하지 않음.
// this.state.contents.push(
// { id: this.max_content_id, title: _title, desc: _desc });
// var _contents = this.state.contents.concat(
// { id: this.max_content_id, title: _title, desc: _desc }
// )
var newContents = Array.from(this.state.contents)
newContents.push({id:this.max_content_id, title:_title, desc:_desc})
this.setState({
// contents: _contents
contents: newContents
})
console.log(_title, _desc);
}.bind(this)}></UpdateContent>
}
return _article;
render()
함수 안의 컨텐츠 호출 부분 수정하기
{/* 컨텐츠 영역에 표시할 내용을 변수로 지정 */}
{this.getContent()}
수정할 input value
값 가져오기
⚠ input value
값을 props
로 가져오면 경고 및 값 변경이 불가능한 오류 발생
<p>
<input type="text" name="title" placeholder="title" value={this.props.data.title}></input>
</p>
👉
props
값은 Read-only이므로onChange
핸들러를 같이 사용하지 않으면 값을 변경할 수 없다는 경고가 뜬다. 따라서props
값을 변경할 수 있는state
값으로 가져와서 변경해야 한다.
❗ input value
값은 state
값으로 가져오고 onChange
핸들러를 추가해 준다.
// value값에 바로 this.props.data.title을 넣으면 props는 read-only값이라 값을 변경하지 못하므로 생성자로 props를 state로 받아서 value를 state값으로써 바꿀 수 있게 해준다.
constructor(props) {
super(props);
this.state = {
title: this.props.data.title,
desc: this.props.data.desc
}
}
inputFormHandler(e) {
this.setState({title: e.target.value});
}
<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>
수정할 textarea
의 내용 state
로 가져오기
⚠ textarea value
로 가져오지 않으면 경고 발생
<p>
<textarea name="desc" placeholder="description">{this.state.desc}</textarea>
</p>
👉
defaultValue
또는value
값을 설정해줘야 한다는 경고가 뜬다.input value
를 설정해준 것처럼textarea
태그 안에value
로state
값을 가져오고onChange
핸들러를 설정해줘야 한다.
❗ textarea value
값을 state
값으로 가져오고 onChange
핸들러를 추가해 준다.
<p>
<textarea name="desc" placeholder="description" value={this.state.desc} onChange={function(e) {
this.setState({desc: e.target.value});
}.bind(this)}></textarea>
</p>
공통으로 사용되는 bind(this)
를 따로 빼주고, title
와 desc
각각에 따라 onChange
핸들러가 동작하도록 변경하기
import { Component } from 'react';
class UpdateContent extends Component {
// value값에 바로 this.props.data.title을 넣으면 props는 read-only값이라 값을 변경하지 못하므로 생성자로 props를 state로 받아서 value를 state값으로써 바꿀 수 있게 해준다.
constructor(props) {
super(props);
this.state = {
title: this.props.data.title,
desc: this.props.data.desc
}
// 공통으로 사용되는 bind(this)를 넣은 값을 변수로 빼준다.
this.inputFormHandler = this.inputFormHandler.bind(this);
}
inputFormHandler(e) {
// [e.target.name]으로 title과 desc값을 각각 변경할 수 있다.
this.setState({[e.target.name]: e.target.value});
}
render() {
console.log(this.props.data);
console.log('UpdateContent render')
return (
<article>
<h2>Update</h2>
<form action="/update_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" value={this.state.title} onChange={this.inputFormHandler}></input>
</p>
<p>
<textarea name="desc" placeholder="description" value={this.state.desc} onChange={this.inputFormHandler}></textarea>
</p>
<p>
<input type="submit"></input>
</p>
</form>
</article>
);
}
}
export default UpdateContent;
컨텐츠의 id
값을 가져오는 코드를 UpdateContent
컴포넌트에 추가하기
return (
<article>
<h2>Update</h2>
<form action="/update_process" method="post"
onSubmit={function(e) {
e.preventDefault();
this.props.onSubmit(
this.state.id,
this.state.title,
this.state.desc
);
}.bind(this)}
>
{/* id값을 가져오는 코드 추가 */}
<input type="hidden" name="id" value={this.state.id}></input>
App.js
에서 컨텐츠의 id
값을 기준으로 해당 id
값을 가진 컨텐츠 내용을 수정하여 배열에 반영하도록 하기
else if(this.state.mode === 'update') {
_content = this.getReadContent();
_article = <UpdateContent data={_content} onSubmit={function(_id, _title, _desc) {
// push()를 사용한 원본 배열 변경은 권장하지 않음.
// this.state.contents.push(
// { id: this.max_content_id, title: _title, desc: _desc });
// var _contents = this.state.contents.concat(
// { id: this.max_content_id, title: _title, desc: _desc }
// )
// 업데이트할 컨텐츠의 id값을 이용해서 해당 id를 가진 컨텐츠를 배열에서 업데이트
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
})
}.bind(this)}></UpdateContent>
}
App.js
에서 update
기능 동작 후에 모드를 read
로 바로 변경해주는 코드 추가
this.setState({
contents: _contents,
mode: 'read'
});
App.js
에서 create
기능 동작 후에 모드를 read
로 바로 변경해주는 코드와 컨텐츠 배열의 맨 마지막 id
값을 변경해주는 코드 추가
this.setState({
contents: _contents,
mode: 'read',
selected_content_id: this.max_content_id
});