생활코딩 강의 들으면서 주석으로 정리한거
읽어보면서 복기하기
App.js
import './App.css';
import React, { Component } from 'react';
import TOC from './components/TOC';
import ReadContent from './components/ReadContent';
import Subject from './components/Subject';
import Control from './components/Control';
import CreateContent from './components/CreateContent';
import UpdateContent from './components/UpdateContent';
//App 컴퍼넌트 클래스로 생성
class App extends Component {
//state 설정 (기본모드 설정)
constructor(props){
super(props);
this.max_content_id = 3;
this.state = {
mode:"welcome",
selected_content_id:2,
//기본적으로 2번 컨텐츠가 선택되게 함.
subject:{title:'Web',sub:'World wide web'},
welcome:{title:'Welcome',desc:'Hello, React.'},
contents:[
{id:1, title:'HTML', desc:'HTML is HyperText....'},
{id:2, title:'CSS', desc:'CSS is Cascading...'},
{id:3, title:'Javascript', desc:'Javascript is for interactive...'}
]
//state는 생성자랑 비슷한데 초기에 내용을 설정해주는 것.
//mode는 read상태, 2번 컨텐츠, contents의 내용 설정을 state로 오브젝트로 설정
}
//state값 초기화하려고...
//실행될 떄 render보다 먼저 실행되면서 그 컴퍼넌트를 초기화시켜주고싶은 코드는
//constructor안에다가 코드를 작성한다.
}
//컴포넌트를 만드는 코드 app이라는 클래스에 component를 상속
//Render()라는 메소드 가지고 있음.
//함수를 만들어서 리팩토링해줌 -1
getReadContent(){
//모드가 read일 때는
var i = 0;
while(i<this.state.contents.length){
//반복문 실행해서 내용 다 보여주게 함
var data = this.state.contents[i]; //현재 순번에 해당하는 콘텐츠
if(data.id === this.state.selected_content_id){
//아이디와 선택한 콘텐츠의 아이디가 같다면 data를 리턴함
return data;
break;
}
i = i + 1;
}
}
//함수를 만들어서 리팩토링해줌 -2
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} sub={_desc}></ReadContent>
//_article에 넣어줌
//state에서 welcome 부분 내용 가져옴
//읽기 모드일 때,
} else if(this.state.mode === 'read'){
var _content = this.getReadContent();
//_content에 함수를 불러옴
_article = <ReadContent title={_content.title} sub={_content.desc}></ReadContent>
//create 모드일 때,
} else if (this.state.mode === 'create'){
//_article에 넣어줌
_article = <CreateContent onSubmit={function(_title, _desc){
//setState를 통해 새로운 content값 추가
this.max_content_id = this.max_content_id + 1;
// this.state.contents.push(
// {id: this.max_content_id, title: _title, desc: _desc}
// );
var _contents = Array.from(this.state.contents);
_contents.push({id: this.max_content_id, title: _title, desc: _desc});
this.setState({
contents:_contents
});
//push대신에 concat을 사용하는 것이 바람직함
//push는 원본 데이터를 변경하지만 concat은 원본을 바꾸지 않고 새로운 데이터를 만들어냄.
this.setState({
contents:_contents,
//원본의 복제본을 setState()로 변경
mode:'read',
selected_content_id:this.max_content_id
});
console.log(_title,_desc);
}.bind(this)}></CreateContent>
//update모드라면..?
} else if (this.state.mode === 'update'){
_content = this.getReadContent();
//getReadContent함수를 불러와 _content에 넣는다.
var _id = _content.id;
//_article에 넣어줌
_article = <UpdateContent data={_content} onSubmit={
function(_id, _title, _desc){
var _contents = Array.from(this.state.contents);
//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
});
console.log(_title,_desc);
}.bind(this)}></UpdateContent>
}
return _article;
//_article로 리턴값을 받아옴.
}
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>
{/* <header>
<h1><a href="/" onClick={function(e){
e.preventDefault();
this.setState({
mode:'welcome'
});
}.bind(this)}>{this.state.subject.title}</a></h1>
{this.state.subject.sub}
</header> */}
<TOC onChangePage={function(id){
this.setState({
mode:'read',
selected_content_id: Number(id)
});
}.bind(this)}
data={this.state.contents}></TOC>
<Control onChangeMode={function(_mode){
//받아온 인자로 모드를 변경함
//delete 모드일 때,
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);
//삭제해준다 splice(배열 인덱스, 삭제할 갯수?)
break;
}
i = i + 1;
}
this.setState({
mode:'welcome',
contents:_contents
})
//삭제하면 모드를 welcome으로 변경하고 변경된 contents로 변경
}
} else {
this.setState({
mode:_mode
});
}
}.bind(this)}></Control>
{this.getContent()}
{/* 함수 불러옴 */}
</div>
);
}
}
export default App;
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');
//여기서 전달한 인자값 create나 update나 delete를 app에 있는 함수에 전달
}.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="button" onClick={function(e){
e.preventDefault();
this.props.onChangeMode('delete');
}.bind(this)}></input></li>
</ul>
);
}
}
export default Control;
CreateContent.js
import { Component } from "react";
class CreateContent extends Component {
render(){
return (
<article>
<h2>Create</h2>
<form action="/create_process" method="post"
//form 태그 입력
onSubmit={function(e){
//Onsubmit 함수 입력
e.preventDefault();
this.props.onSubmit(
e.target.title.value,
e.target.desc.value
);
//입력된 제목과 내용을 받아옴
}.bind(this)}
>
<p><input type="text" name="title" placeholder="title"/></p>
<p>
<textarea name="desc" placeholder="description"></textarea>
</p>
<p>
<input type="submit"></input>
</p>
</form>
</article>
);
}
}
export default CreateContent;
UpdateContent.js
import { Component } from "react";
//Update 컴포넌트
class UpdateContent extends Component {
//state로 id, title, desc값을 설정해줌
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(this.props.data);
console.log('Update content Render');
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)}
>
<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}/>
</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;
update 부분은 아직 미완성 ..!
React 19.7 - shouldComponentUpdate() 관련
TOC부분이 자기가 관련 없는 부분에도 쓸데없이 렌더링 되는 것을 막을 수 있다!
그리고 예전 값과 새로운 값에 접근할 수 있다.
근데 이거는 큰 프로그램이라서 성능을 향상시켜야할 이슈가 있다면 해당하는 거고
작은 프로그램이라면 따로 concat을 써 복제본을 만들지 않고 그냥 push로 진행해도 된다.
빨리 진도 나가는데 급급하지 말고 하나라도 이해하는 걸 중점적으로 하자 ..
항상 급하게 하다가 다시 돌아오는게 너무 비효율적임
복제할 때 배열은 Array.from을 통해서 복제 가능하고
객체는 Object.assign()을 통해 복제 가능하다
복제된 것들은 내용은 같지만 엄연히 다름.
'develop > React' 카테고리의 다른 글
React : public 폴더 이미지 절대경로로 사용하기 (0) | 2021.10.01 |
---|---|
React : useRef() 사용 (0) | 2021.09.27 |
React 4: 함수형과 클래스형 (0) | 2021.08.22 |
React 2 : props, state (0) | 2021.07.19 |
React 1 : 컴포넌트(Component) (0) | 2021.07.18 |