생활 코딩 리액트 강의 <https://www.youtube.com/playlist?list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi
지금까지 우리는 CRUD(Create, Read, Update, Delete) 중 Read까지했음
이 장부터 create 구현
19.1부터 create 구현:소개
하려고 하는 것
- toc와 content 사이에 새로운 컴포넌트를 만들어 생성/수정/삭제 버튼을 구현
- 생성 버튼 클릭 시: App 컴포넌트에 mode가 read->create로 바뀔 것
그에 따라 Content, 읽기에서 사용되는 컴포넌트가, 글을 추가할 때 사용되는 컴포넌트로 바뀔 것.
- 이 컴포넌트에는 form이 들어가 있을 것.
- form에 정보를 입력, submit 버튼 클릭 시
- App 컴포넌트에 contents 목록에 새로운 컴포넌트 정보가 id,제목,본문이 객체로 담겨 contents에 추가될 것임
- 새로 추가한 컴포넌트를 클릭하면 mode가 다시 create->read로 바뀌고, selected_content_id가 해당 id로 바뀌고, 본문에 ( TOC에) 해당 내용이보여질 것임
1-1. TOC와 CONTENT 사이에 CREATE,UPDATE,DELETE mode로 진입할 수 있는 버튼 만들기
- create,update,delet에 href 태그와 button 추가하기
<ul>
<li> <a href="/create">create</a></li>
<li> <a href="/update">update</a></li>
{/*delete는 링크를 사용하지 않고(페이지 개념이 아닌) 버튼(오퍼레이션 개념)을 사용
이유: 빠른 동작을 위해 해당 페이지를 미리 방문을 해두는 소프트웨어가 구현되어 있다고 치면,
delete도 링크로 구현되어 있으면 delete도 미리 방문해서 삭제해버릴수도 있기 때문*/}
<li> <input type="button" value="delete"></input></li>
</ul>
- App.js에 있던 위 코드를 Control이라는 새로운 컴포넌트를 만들어 밖으로 빼는 작업 진행
Control.js
import React, {Component} from 'react';
class Control extends Component {
render() {
console.log('subject render'); //render 호출되는지 로그 찍어보기
return (
<ul>
<li> <a href="/create">create</a></li>
<li> <a href="/update">update</a></li>
{/*delete는 링크를 사용하지 않고(페이지 개념이 아닌) 버튼(오퍼레이션 개념)을 사용
이유: 빠른 동작을 위해 해당 페이지를 미리 방문을 해두는 소프트웨어가 구현되어 있다고 치면,
delete도 링크로 구현되어 있으면 delete도 미리 방문해서 삭제해버릴수도 있기 때문*/}
<li> <input type="button" value="delete"></input></li>
</ul>
);
}
}
export default Control;
App.js
{/*생략*/}
import Control from "./components/Control";
{/*생략*/}
<Control></Control>//해당 위치에
{/*생략*/}
2-1. Control 컴포넌트에서 3개 중 하나를 클릭 시 mode가 바뀌게 만들기
- Control 컴포넌트에 onChangeMode라는 이벤트를 정의하여 이벤트 핸들러를 설치
(=이벤트가 실행되어야 하는 함수를 핸들러라고 부름)
<Control
onChangeMode={function(){
}.bind(this)}
></Control>
- 이 핸들러를 설치한 후, create/update/button을 클릭했을 때 onChangeMode핸들러가 실행되게 할 것임
<a href="/create"
onClick={function(e) {
this.props.onChangeMode('');
}>
<a href="/update"
onClick={function(e) {
this.props.onChangeMode('');
}>
<input
onClick={function(e) {
this.props.onChangeMode('');
}>
- 그리고 해당 버튼 클릭할때마다 onChangeMode에게 나는 create야~ 나는 update야~를 알려 주는 것
this.props.onChangeMode('create');
this.props.onChangeMode('update');
this.props.onChangeMode('delete');
- 이렇게 알려주면 (=onChangeMode가 호출될때) 알려주는 것을 받는 _mode라는 첫번째 인자를 만들고
onChangeMode={function(_mode){
- 받은 인자의 mode로 바꿔 주면 됨
this.setState({
mode:_mode,
})
- 풀 코드
App.js 중 바뀐 부분
<Control onChangeMode={function(_mode){ this.setState({ mode:_mode, }) }.bind(this)} ></Control>
Control.js 중 바뀐 부분
<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>
2-2. mode에 따라 Content에 적절하게 내용이 변경되게 하기
- Content.js 파일 한개로 이루어졌던 것을 ReadContent로 이름 변경, CreateContent는 새로 생성해 바꾸기
CreateContent.js
import React, {Component} from 'react';
class CreateContent extends Component {
render() {
console.log('Content render'); //render 호출되는지 로그 찍어보기
return(
<article>
<h2>Create</h2>
<form>
</form>
</article>
);
}
}
export default CreateContent;
- ReadContent가 표시될 자리에 하나의 변수를 두어 가변적으로 움직일 수 있게 변경
변경 전 App.js 일부 코드
<ReadContent title={_title} desc={_desc}></ReadContent>
변수로 변경 후 App.js 일부 코드
var _article = null;
{/*원래 코드가 있던 위치에*/} {_article}
- mode가 welcome이거나 read일 때는 default로 mode가 ReadContent이게 설정 해주기
if(this.state.mode === 'welcome') {
{/*생략*/}
_article = <ReadContent title={_title} desc={_desc}></ReadContent>
} else if(this.state.mode === 'read') {
{/*생략*/}
_article = <ReadContent title={_title} desc={_desc}></ReadContent>
}
- if-else if 문에 read뿐만 아니라 mode가 create일 때 조건 도 만들어주기
else if(this.state.mode === 'create'){
_article = <CreateContent></CreateContent>
}
2-3. CreateContent의 form 영역 구현
- Title 적는 박스, Description 적는 박스, submit 버튼 UI 구현
CreateContent.js 일부
여기서 placeholder는:
form에 아무것도 입력하지 않았을 때 디폴트로 보여지는 텍스트를 설정할 때 사용
<form>
<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>
form 태그 자체를 정의하기
데이터를 어디다 전송할지 action값을 줌
action="/create_process" 는
create_process라는 페이지로 사용자가 입력한 정보를 전송할 것이다를 뜻함
method="post"로 정해 url에 노출안되게 넘기기
onSubmit이라는 이벤트를 호출
submit 버튼을 포함한 전체 form 태그에 onSubmit이라는 이벤트를 설치해두면, 그 이벤트가 실행되도록 약속을 하는 것과 마찬가지 (->html form 태그의 고유 기능)
e.preventDefault();는 앞 강의에서도 말했다싶이 화면전환을 방지하기 위함임.
이 문장이 없다면 submit 버튼 클릭시 form태그의 action이 가리키고 있는 페이지로 화면이 이동될 것임
CreateContent.js 일부
<form action="/create_process" method="post"
onSubmit={function(e){
e.preventDefault();
alert('submit complete');
}.bind(this)}>
3-4. 입력된 데이터를 CreateContent를 가져다 쓰고 있는 App 컴포넌트의 contents라는 데이터 끝에다 추가하기
- Submit 버튼 클릭 시 App.js CreateContent의 이벤트로 설치된 함수를 실행 시키려고 함. && 이 함수의 인자로 title과 desc를 전달받을 것임
else if(this.state.mode === 'create'){
_article = <CreateContent onSubmit={function(_title,_desc){
//add content to this.state.contents
}.bind(this)}></CreateContent>
}
- CreateContent.js에선 App.js CreateContent의 onSubmit이라는 props를 호출 할 것임
<form action="/create_process" method="post"
onSubmit={function(e){
e.preventDefault();
debugger;
this.props.onSubmit(첫번째인자(제목),두번째인자(본문내용));
alert('submit complete');
}.bind(this)}>
- 그렇담,, App.js에 넘겨줄 제목과 본문내용 데이터를 어떻게 표현-할 것인가?
-> debugger; 이용! (아래 사진 참고)
이를 통해 title과 description은 내부적으로
e.target.title.value
e.target.desc.value라는 것을 알 수 있음
이를 그대로 props의 인자로 넘겨주면 됨
this.props.onSubmit(
e.target.title.value,
e.target.desc.value);
- 마지막으로, 얻어온 데이터를 contents 데이터 끝에다 추가해주면 됨
-지금까지의 contents id가 몇번인지 알아내기
this.max_content_id=3;
state값으로 하지 않고 객체의 값으로 함.
max_content_id는 단순히 id값을 알아낼때 사용하는 것일뿐 ui와 상관없어서 불필요한 렌더링을 피하기 위해 씀
-알아낸 id번호에 +1을 하고, title과 desc를 추가해줌
this.max_content_id=this.max_content_id+1;
this.state.contents.push(
{id:this.max_content_id,title:_title,desc:_desc}
);
하지만 위 코드 틀림
-> react에게 state가 변경되었다고 알리기 위해 setState를 써줘야 함
this.max_content_id=this.max_content_id+1;
this.state.contents.push(
{id:this.max_content_id,title:_title,desc:_desc}
);
{/*밑 부분 추가*/}
this.setState({
contents:this.state.contents
});
-push대신 concat쓰게 변경
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
});
'JAVASCRIPT > React' 카테고리의 다른 글
[생활코딩 React 강의] Immutable이란? (concat, shouldComponentUpdate, Array.from, Object.assign) (0) | 2019.08.20 |
---|---|
[생활코딩 React 강의 5] 이벤트 설치해보기 응용 (0) | 2019.05.19 |
[생활코딩 React 강의 4] 이벤트 설치해보기 (0) | 2019.05.18 |
[생활코딩 React 강의 3] State란? state 사용해보기 (0) | 2019.04.26 |
[생활코딩 React 강의2] 컴포넌트 만들기, Props, 컴포넌트 파일로 쪼개기 (0) | 2019.04.26 |
Comments