IT,프로그래밍/React.js

[생활코딩] 5# 리액트 공부

state 와 props 의 차이점

  • Props

    • Read only 이다

    • 수정할수 없다

    • 따라서 컴포넌트 내부에서 변경하려한면 에러가 뜬다

      render(){ this.props.title = "hi"//error return( <article> <h2>{this.props.title}</h2> {this.props.desc} </article> ) }

CRUD

CRUD 를 위한 버튼들을 만들어 주도록 하자

<TOC onChangePage={function(id){ this.setState({ mode:'read', selected_content_id : Number(id) }) }.bind(this)} data={this.state.contents}></TOC> <ul> <li><a href="/create">carete</a></li> <li><a href="/update">update</a></li> <li><input type="button" value="delete"></input></li> </ul> <Content title={_title} desc={_desc}></Content>

Delete 의 경우는 link 의 개념으로 잡는데아닌 오퍼레이션의 기능을 하는 버튼을 만들어야 한다

위의 컨트롤 부분 소스를 다른 컴포넌트 js 파일로 분리 시키자

import React,{ Component } from 'react'; import logo from './logo.svg'; import TOC from "./components/TOC"; import Content from "./components/Content"; import Subject from "./components/Subject"; import Control from "./components/Control"; // 컴포넌트 추가 import './App.css'; . . . <TOC onChangePage={function(id){ this.setState({ mode:'read', selected_content_id : Number(id) }) }.bind(this)} data={this.state.contents}></TOC> <Control></Control>//컴포넌트 추가 <Content title={_title} desc={_desc}></Content>

app.js

import React,{ Component } from 'react'; class Control extends Component{ render(){ console.log("Subject Render"); return ( <ul> <li><a href="/create">carete</a></li> <li><a href="/update">update</a></li> <li><input type="button" value="delete"></input></li> </ul> ); } } export default Control;

Control.js

이후 Control.js 에 이벤트를 달아줘서 `App.js` 에 있는 state 의 mode 를

변경할수 있도록 해줍니다

return ( <ul> <li><a href="/create" onClick={function (e) { e.preventDefault(); this.props.onChangeMode('create'); }.bind(this)}>carete</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="delete" onClick={function (e) { e.preventDefault(); this.props.onChangeMode('delete'); }.bind(this)}></input></li> </ul> );

이다음에 하위 컴포넌트인 `Control.js` 에서 onClick 이벤트에 핸들러를

추가해서 state 변경이 가능하도록 함수를 추가하여준다.

<Control onChangeMode={function (_mode) { this.setState({ mode : _mode }) }.bind(this)}></Control>

이로서

클릭에 따라 mode 가 변하게 만들었다!

Mode 에 따라 다른 content 보여주기

readcontent

우선 read 와 create 컴포넌트를 따로 만들어준다

import React,{ Component } from 'react'; class ReadContent extends Component{ render(){ return( <article> <h2>{this.props.title}</h2> {this.props.desc} </article> ) } } export default ReadContent;

read

import React,{ Component } from 'react'; class CreateContent extends Component{ render(){ return( <article> <h2>Create</h2> <form> </form> </article> ) } } export default CreateContent;

Create

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 i = 0; while (i<this.state.contents.length) { var data = this.state.contents[i]; if(data.id === this.state.selected_content_id){ _title = data.title; _desc = data.desc; break; } i=i+1; } _article = <ReadContent title={_title} desc={_desc}></ReadContent>; }

위에 소스와 같이 read 와 welcome mode 일때만 readcontent 를 보여주기위해

소스를 작성해준다.

CreateContent

아까 read 와 같이 create mode 일 경우에도 변경이 되도록 분기 처리를 해주자

import React,{ Component } from 'react'; import logo from './logo.svg'; import TOC from "./components/TOC"; import ReadContent from "./components/ReadContent";//추가 import CreateContent from "./components/CreateContent";//추가 import Subject from "./components/Subject"; import Control from "./components/Control"; import './App.css';

readcontent 추가 할때 빼먹었는데 상단에 import 해주자

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 i = 0; while (i<this.state.contents.length) { var data = this.state.contents[i]; if(data.id === this.state.selected_content_id){ _title = data.title; _desc = data.desc; break; } i=i+1; } _article = <ReadContent title={_title} desc={_desc}></ReadContent>; } else if (this.state.mode === "create") {//분기추가 _article = <CreateContent></CreateContent>; }

create 분기를 추가해서 mode 가 create 일때 CreateContent 가 나오도록 만들었다.

이후 CreateContents 를 수정해준다

import React,{ Component } from 'react'; class CreateContent extends Component{ render(){ return( <article> <h2>Create</h2> <form action="/create_process" method="post" onSubmit={function (e) { e.preventDefault(); alert('Submit!!!'); }.bind(this)} > <p> <input type="text" name="title" placeholder="name"> </input> </p> <p> <textarea name="desc" placeholder="description"></textarea> </p> <p> <input type="submit"></input> </p> </form> </article> ) } } export default CreateContent;

여기서 우리는 페이지 이동이 없는 SPA 페이지 를 만들거기 때문에

form 에서 submit 이 안되도록 `onSubmit` 이벤트를 재정의 해줍니다.

이제 `app.js` 에 있는 onSubmit 함수를 수정해 줍니다

} else if (this.state.mode === "create") { _article = <CreateContent onSubmit={function (_title, _desc) { }.bind(this)}></CreateContent>;

위와 같이 _title, _desc 라는 파라미터를 받도록 수정해줍니다

이후 `CreateContent` 에서 아까 정의 해둔 이벤트 핸들러를 수정해줍니다

<form action="/create_process" method="post" onSubmit={function (e) { e.preventDefault(); this.props.onSubmit( e.target.title.value, e.target.desc.value ); }.bind(this)} >

e 를 console 창에 출력했을 경우

  • e

    • target

      • title

      • desc

와 같이 name 으로 지정해준 이름으로 e 객체안에 담겨있는걸 확인할수 있습니다.

따라서 이값들을 파라미터로 던져 줍니다.

그리고 받은 파라미터를 state 에 적용시켜주는 함수를 코딩합니다

<CreateContent onSubmit={function (_title, _desc) { this.max_content_id = this.max_content_id +1; this.state.contents.push( {id:this.max_content_id, title:_title, desc: _desc}//새로운 값을 state 에 추가하여준다. ); this.setState({ contents:this.state.contents //새롭게 추가된값을 setState 를 이용해 적용 시켜준다 }); }.bind(this)}></CreateContent>;

위와같이 setState 를 해서 react에 값이 변경되었음을 set해준다.

push 와 concat

배열을 추가하는 방법이 2가지가있는데 **push 와 concat 이다**

Push 는 원본의 배열을 변경하지만

Contcat 은 추가된 배열을 **리턴** 해준다

var arr = [1,2] arr.push(3) //arr = [1,2,3] var arr2 = [1,2] var result = arr2.concat(3) //result = [1,2,3] //arr2 = [1,2]

따라서 값을 변경할때는 원본을 건드리지 않도록 push 가 아닌 concat 을 쓰도록하자

따라서 원본을 바꾸지 않고 데이터를 변경하기 위해 함수를 수정해주자

} else if (this.state.mode === "create") { _article = <CreateContent onSubmit={function (_title, _desc) { this.max_content_id = this.max_content_id +1; // this.state.contents.push( // {id:this.max_content_id, title:_title, desc: _desc}//새로운 값을 state 에 추가하여준다. // ); var _contents = this.state.contents.concat( {id:this.max_content_id, title:_title, desc: _desc} ) this.setState({ contents: _contents //새롭게 추가된값을 setState 를 이용해 적용 시켜준다 }); }.bind(this)}></CreateContent>;