Update는 Create + Read 기능이 더해져있다.
최종 목표
업데이트 기능 구현하기 - Create의 폼에 입력받은 기존 컨텐츠의 내용을 수정한다.
App.js
1. 렌더함수 return에 <UpdateContent>자리를 만든다.
1-1. 추후에 이 자리를 대신하여 {this.getContent()} 함수가 들어간다.
만들고 보니 너무 복잡하다. 흠... 함수를 좀 나누어 정리해야지
2. getContent()라는 함수를 만들어 깔끔하게 CRUD자리를 치워놓자.
3. render()함수의 내용 (if문이 있는 로직부분) 그대로 가져오기 + 리턴은 _article 값 넣어주기 (1-1로 돌아가시오)
4. else if문 (모드===update) 일 때 ver. 추가하기
- _content 변수를 getReadContent()를 불러내는 소환문으로 선언해놓고
<UpdateContent data=_content>로 getReadContent()함수의 data들을 소환한다. 즉, 이미 저장된 글목록(데이터 배열)을 나타낸다.
그래야 수정을 하던가 말던가 하지... 자 그럼 getReadContent()를 만들러 가보자! (5로 가시오)
- onSubmit이벤트를 통해 서밋버튼을 누르면 일어나는 일들을 적어보자 {
- 핸들러메소드로 받는 인자인 id는 새로등록된 글번호를, title, desc은 사용자로부터 입력된 데이터들을 의미한다. (준비물)
- 저 재료들로 요리를 해보자. 일단 Array.from()으로 원본 배열 contents를 담는 복사본배열 _contents 을 만든다. (이름이 비슷하쥬)
- while문으로 복사본배열을 돌려서 하나하나씩 나열하는데 ...! 조건이 있음. 기존글 id 랑 = 입력글 id가 같으면..(아랫줄로가시오)
- 기존의 id, title, desc를 인자로 받은(사용자가 입력한) _id, _title, _desc로 교체하라.. (즉 덮어씌우라 이말이야)
}
- onSubmit 잘 실행됬겠지? 그렇다면 state를 변경할 차례 (reason why? 재탕해야하니까 + 결과화면이 좀 달라져야지) {
- _content 는 새로입력된 걸로 교체좀 하자 ^^
- 읽기모드로 좀 바꾸자 (그래야 수정완료하면 수정된 결과페이지가 짠하고 나오지)
}
5. getReadContent()함수 만들기
- 모드가 read일 때, while문으로 반복하여 그간 저장한 데이터 배열을 나열하는 기능을 가진 함수다.
- getContent ()안의 read 모드는 this.getReadContent()을 호출하면 제곧내가 된다.
**전체코드보기(복사용 첨부 / 더보기클릭)
import React, { Component } from 'react';
import Subject from "./components/Subject.js";
import Main from "./components/Main.js";
import Control from "./components/Control.js";
import CreateContent from "./components/CreateContent.js";
import UpdateContent from "./components/UpdateContent.js";
import ReadContent from "./components/ReadContent.js";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.max_content_id = 3;
this.state = {
mode:'read',
selected_content_id:1,
head:{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'}
]
}
}
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;
break;
}
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){
this.max_content_id += 1;
var _contents = Array.from(this.state.contents);
_contents.push({id:this.max_content_id, title:_title, desc:_desc});
this.setState({
contents:_contents,
mode:'read',
selected_content_id:this.max_content_id
});
console.log(_title, _desc);
}.bind(this)}></CreateContent>
} else if(this.state.mode === 'update'){
_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'
});
console.log(_title, _desc);
}.bind(this)}></UpdateContent>
}
return _article;
}
render() {
console.log('App render');
return(
<div className="App">
<Subject
title={this.state.head.title}
sub={this.state.head.sub}
onChangePage={function(){
this.setState({mode:'welcome'});
}.bind(this)}>
</Subject>
<Main
onChangePage={function(id){
this.setState({
mode:'read',
selected_content_id:Number(id)
});
}.bind(this)}
data={this.state.contents}>
</Main>
<Control onChangeMode={function(_mode){
this.setState({
mode:_mode
})
}.bind(this)}></Control>
{this.getContent()}
</div>
);
}
}
export default App;
UpdateContent.js
1. 생성자 함수 안의 state에 사용할 재료들을 좀 선언해주자
2. <input>과 <textarea>에 기존에 사용자가 입력한 내용을 가져오기
- <input value={this.state.title}>로 App.js의 data에서 가져온 state인 title을 넣는다.
- <input value={this.state.desc}>로 App.js의 data에서 가져온 state인 desc을 넣는다.
**어 근데 수정이 안되요?
- props 자체는 Read Only이기 때문에 state로 선언해서 setState로 변경가능하게 만들어 줘야 합니다^^
- 하지만 여전히 수정은 안됨. onChange를 사용하여 setState로 state값이 바뀌는 이벤트를 만들어요 (3번으로 가시오)
입력창에 변화가 일어났을 때 이벤트가 발생하게 됩니다
3. 근데... 이런식으로 onChange를 하나하나 선언해주는건 너무 코드중복이 많다.
onChange에 ={this.inputFormHandler} 이런식으로 핸들러메소드를 따로 빼서 만드는 소환술을 사용해보자
4. onChange 핸들러메소드만 따로 빼서 inputFormHandler() 라고 이름붙여준다. {
- 그리고 setState를 사용해서 값을 바꾸려 하는데..
- this.setState({title:e.target.value}); → 이러면 타이틀값만 바뀜.
- 이럴 때는 어떻게 해야할까?
- this.setState({[e.target.name]:e.target.value}); → state에 맞게 내용이 변경이 된다
}
** [e.target.name]:e.target.value 처럼 key를 [ ]로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key 값으로 사용됩니다.
→ 해당 input태그의 name을 가리킨다.
5. onChange={this.inputFormHandler.bind(this)} bind() 얘도 매번 중복된다. 따로 빼주자
constructor에서 {
this.inputFormHandler = this.inputFormHandler.bind(this);
}
이렇게 바꿔주면
onChange={this.inputFormHandler} → 밑에 렌더함수에서 소환할 때 간단하게 줄여쓸 수 있음
6. 업데이트 시, 폼안에 데이터를 전송할 식별자를 만들어준다.
<input type="hidden" name="id" value={this.state.id}>
→ hidden은 개발자들에게만 보인다. 폼을 서밋하면 name으로 받은 id 값이 서버 쪽으로 넘어간다.
→ 예를들어서 회원가입시 사용자의 아이피를 받는 경우 히든필드에 넣어서 폼 전송시 함께 전송한다.
7. <form> 안에 onSubmit 이벤트 만들기
**전체코드보기(복사용 첨부 / 더보기클릭)
import React, { 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
}
this.inputFormHandler = this.inputFormHandler.bind(this);
}
inputFormHandler(e){
this.setState({[e.target.name]:e.target.value});
}
render() {
console.log('UpdateContent 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={this.inputFormHandler}
></input>
</p>
<p>
<textarea
name="desc"
placeholder="description"
value={this.state.desc}
onChange={this.inputFormHandler}
></textarea>
</p>
<p>
<input type="submit" value="submit" />
</p>
</form>
</article>
);
}
}
export default UpdateContent;
'React' 카테고리의 다른 글
React - snippets 단축키사용 'rafce' (0) | 2021.01.22 |
---|---|
React(19) Delete 구현 (0) | 2021.01.12 |
React(17) Immutable 개념 (0) | 2021.01.08 |
React(16) Create 구현 : shouldComponentUpdate (0) | 2021.01.08 |
React(15) Create 구현 : onSubmit이벤트 & contents변경 (0) | 2021.01.07 |
댓글