React๋ฅผ ์ฒ์ ๊ณต๋ถํ๋ฉด์ ์๋ํ๋ ์ฌ๋ฌ๊ฐ์ง ์์ ํ๋ก์ ํธ์ ์์ค์ฝ๋๋ฅผ ๋ด์ ์ ์ฅ์์
๋๋ค.
์๋๋ ์ํ์ฝ๋ฉ ๋ฆฌ์กํธ ๊ธฐ์ด ๊ฐ์ข๋ฅผ ๋ค์ผ๋ฉฐ ์ ๋ฆฌํ ๋ด์ฉ์
๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋๋ก์จ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
๊ฐ์ฅ ํฐ ํน์ง์ ์ฌ์ฉ์ ์ ์ ํ๊ทธ(์ปดํฌ๋ํธ)๋ฅผ ๋ง๋ค์ด์ฃผ๋ ๊ธฐ์ ์ด๋ผ๋ ๊ฒ.
- ๊ฐ๋ ์ฑ์ด ๋์(ํ๊ทธ๋ช ๋ง์ผ๋ก ๊ตฌ์กฐ๋ฅผ ํํ ๊ฐ๋ฅ)
- ์ฌ์ฌ์ฉ์ฑ์ด ๋์
- ์ ์ง๋ณด์๊ฐ ์ฌ์
- JSX ๋ฌธ๋ฒ์๋ ์ต์ํด์ ธ์ผ ํ๋ค! ๋ณ์๋ฅผ ๋ฃ์ ๋๋ ์ค๊ดํธ{} ์์ ๋ด์์ผ ํจ์ ๊ธฐ์ตํ์.
- ๋ก์ปฌ์์ ์คํ ํ๋ฉด์ ํ์ธํ ๊ฒฝ์ฐ : npm run start ์ฌ์ฉ
- ๋ฐฐํฌํ ๊ฒฝ์ฐ : npm run build ์ฌ์ฉ(๋ฌด์๋ฏธํ ๊ณต๋ฐฑ ๋ฑ์ ์์ ์ฉ๋์ ์ต์ํ์ผ๋ก ์ค์)
- Document Object Model : ๋ฌธ์ ๊ฐ์ฒด ๋ชจ๋ธ(HTML ๋จ์ ํ๋ํ๋๋ฅผ ๊ฐ์ฒด๋ก ์๊ฐํ ๋ชจ๋ธ)
- ๋ ๋ํธ๋ฆฌ๊ฐ ๋งค๋ฒ ์ฌ์์ฑ๋๋ ๊ฒ์ ์ข์ง ์์. ๋ฐ๋ผ์ ๊ฐ์ ๋์ ๋ณํ๋ฅผ ๊ฐ์ ๋์์ ๋ฏธ๋ฆฌ ์ธ์งํด ๋ณํ์ํด.
- ์ด ์์ ์ ์ค์ DOM ์๋๊ธฐ ๋๋ฌธ์ ๋๋๋ง๋์ง ์๊ณ ์ฐ์ฐ ๋น์ฉ์ด ์ค์ DOM๋ณด๋ค๋ ์ ์.
- ์ด ๊ฐ์ DOM์ ๋ณํ๋ฅผ ๋ง์ง๋ง์ ์ค์ DOM์๊ฒ ๋์ ธ์ฃผ์ด, ๋ชจ๋ ๋ณํ๋ฅผ ํ ๋ฒ์ ๋๋๋ง ๋๊ฒ ํจ.
- ์ฆ, ๊ฐ์ ๋์ ๋ฐ๋์ง ์์ ๋ถ๋ถ๊ณผ ๋ฐ๋ ๋ถ๋ถ์ ์๋์ผ๋ก ๊ฐ์งํด์ ์ ๋ฐ์ดํธ ์์ผ์ค๋ค๋ ๋ง์ธ๋ฐ...
- ์ฌ์ค ์ํ์ฝ๋ฉ์์ DOM์ ๋ํ ๋ด์ฉ์ ๋ค๋ฃจ์ง ์์์ ๋ฌด์จ ๋ง์ธ์ง ์ ํํ๋ ๋ชจ๋ฅด๊ฒ ์. ๋ ์ฐพ์๋ณด๊ธฐ.
ReactStudy
|
| - public : ๊ฐ์ DOM์ด ๋ค์ด๊ฐ ๋น ๊ป๋ฐ๊ธฐ(?) html์ด ์กด์ฌํ๋ ํด๋
| - src : ๋ฆฌ์กํธ ๊ฐ๋ฐ์ด ์ด๋ฃจ์ด์ง๋ ๋ฉ์ธ ํด๋
public/manifest.json : ์น ์ฑ ๋งค๋ํ์คํธ๋ ์ฌ์ฉ์๊ฐ ์ฑ์ ๋ณผ ๊ฒ์ผ๋ก ์์๋๋ ์์ญ์ ์น ์ฑ์ด๋ ์ฌ์ดํธ๋ฅผ ๋ํ๋ด๋ ๋ฐฉ์์ ๊ฐ๋ฐ์๊ฐ ์ ์ดํ๊ณ , ์ฌ์ฉ์๊ฐ ์์ํ ์ ์๋ ํญ๋ชฉ์ ์ง์ํ๊ณ , ์์ ์์ ๋ชจ์ต์ ์ ์ํ ์ ์๋ JSON ํ์ผ์ ๋๋ค.(๊ตฌ๊ธ์์ ์ ์ํ ๋ด์ฉ)
- ํ๋ฉด์ html ๋ทฐ๋ฅผ ์์ฑํด์ฃผ๋ ์ญํ ์ ํจ
- return์ผ๋ก ๋ฐ๋ ๊ฐ๋ค์ ๋์ค์ html ์ฝ๋๋ก ๋ฐ๋๋ค.
- ์ํ์ฝ๋ฉ์์๋ ํด๋์คํ์ ์ฌ์ฉํด ๊ฐ์๋ฅผ ์งํํ์.
๋์ค์ ๋ฆฌ์กํธ์ ์ด๋์ ๋ ์ต์ํด์ง๋ฉด ์ฐพ์๋ณด๊ธฐ. ์ง๊ธ์ ๋ฆฌ์กํธ๋ ์นํด์ง๋๊ฒ ๋จผ์ !
class Subject extends Component {
render() {
return (
<header> //์ปดํฌ๋ํธ์์๋ ํ๋์ ์ต์์ ํ๊ทธ๋ง ์ฌ์ฉํด์ผ ํ๋ค.
<h1> ํ์ดํ </h1>
๋ด์ฉ์ด ์ด์ฉ๊ตฌ ์ ์ฉ๊ตฌ
</header>
);
}
}
class App extends Component {
render() {
return (
<div className = "App">
<Subject></Subject> //์ด๋ฐ ์์ผ๋ก ์์์ ํ๊ทธ๋ฅผ ์ ์ํด ์ฌ์ฉํ ์ ์๋ค. ์ด ๋ถ๋ถ์ ์์ ์์ฑํ Subject์ ์ฝ๋๊ฐ ์ ์ฉ๋๋ค.
</div>
);
}
}
export default App;
๋ผ์ฐํ ์ด๋ ๋น์ทํ ๊ฐ๋ ์ธ ๋ฏ. Subject.js ํ์ผ์ Subject ์ฝ๋๋ฅผ ์ฎ๊ฒจ๋๊ณ App.js์์ ํด๋น ๊ฒฝ๋ก๋ฅผ importํด์ฃผ๋ฉด App์์ ๊ทธ๋๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
import Subject from "./components/Subject";
๋จ ํ์ผ์ ๋ถ๋ฆฌํ ๊ฒฝ์ฐ Subject ์ฝ๋์ ํ์ํ ์์๋ค์ Subject.js์์ ๋ชจ๋ import ํด์ฃผ์ด์ผ ์ค๋ฅ๊ฐ ๋์ง ์๋๋ค.
- state : ํ๋์ ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ง ์ ์๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ. ๋ด๋ถ์ ์ผ๋ก ํ์ํ ๋ฐ์ดํฐ๋ ์ํ๋ state๋ฅผ ํตํด ๊ด๋ฆฌํ๋ค.
- props : ํ์ฌ ์ปดํฌ๋ํธ ๋ด์์๋ ๋ณ๊ฒฝ์ด ๋ถ๊ฐ๋ฅํ๋ค.
- state์ props ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ์ ์์์ด ๊ฐ๋ฅํ๋ค.
๋ด๋ถ์ ์ผ๋ก ํ์ํ ๋ฐ์ดํฐ๋ ์ํ๋ state๋ฅผ ํตํด ๊ด๋ฆฌํ๋ค.
props์ state ๋ชจ๋ render ํจ์ ํธ์ถ์ ์ ๋ํ๊ธฐ ๋๋ฌธ์, UI๊ฐ ๋ณ๊ฒฝ๋์ด์ผ ํ๋ ๋ถ๋ถ์์ ์ ์ ํ๊ฒ ํ์ฉํด์ผ ํ๋ค.
props์ read-only์ ์๋ฏธ : ์ฌ์ฉํ๋ ์ชฝ์์๋ props๋ฅผ ๋ณ๊ฒฝ ๊ฐ๋ฅํ์ง๋ง, ์ปดํฌ๋ํธ ๋ด๋ถ์์๋ ์ ๋ฌ ๋ฐ์ props์ ์์ ํ ์ ์๋ค.
์์ ์ปดํฌ๋ํธ์์ ํ์ ์ปดํฌ๋ํธ์ state๋ฅผ ๋ฐ๊ฟ ๋๋ props ์ฌ์ฉ
ํ์ ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ์ state๋ฅผ ๋ฐ๊ฟ ๋๋ event ์ฌ์ฉ
์ธ๋ถ์์๋ props๋ฅผ ํตํด์ ์ปดํฌ๋ํธ ๋ด๋ถ์ state๋ฅผ ์ ์ด
์ปดํฌ๋ํธ๋ props์ state์ ์ํฅ์ ๋ฐ๋ผ์ ์ค์ DOM์ ์ํฅ์ ์ค UI๊ฐ ๊ทธ๋ ค์ง
component๊ฐ ์คํ๋ ๋, render ํจ์๋ณด๋ค ๋จผ์ ์คํ๋๋ฉด์ component๋ฅผ ์ด๊ธฐํํ๊ณ ์ถ์ ๋ constructor๋ฅผ ์ฌ์ฉํ๋ค.
class App extends Component {
constructor(props){ //props๋ฅผ ํ์ฉ(๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋ค๋ฅธ ๋ด์ฉ์ผ๋ก ์ฌ์ฌ์ฉ)
super(props);
this.state = {
subject:{title:'WEB', sub:'World Wide Web!'}, //์ธ๋ถ์์ ๋ด๋ถ ์ ๋ณด๊ฐ ๋ณด์ด์ง ์๋๋ก ์๋ํ๋ ๊ฒ์ด ์ฌ์ฌ์ฉ์ฑ์ ํต์ฌ
//์ฌ๋ฌ๊ฐ์ state๋ฅผ ์ ์ํ ๊ฒฝ์ฐ ๋ฐฐ์ด ์ฌ์ฉ
content:[
{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'}
]
}
}
์์์ ์์ฑํ ์ฝ๋์ฒ๋ผ ์์ ์ปดํฌ๋ํธ์ state ๊ฐ์ ์๋ ์ฝ๋์ฒ๋ผ ํ์ ์ปดํฌ๋ํธ์ props ๊ฐ์ผ๋ก ์ ๋ฌ ๊ฐ๋ฅ
render() {
return (
<div className = "App">
<Subject
title = {this.state.subject.title} //๋ฌธ์๊ฐ ์๋ ์ฝ๋๋ก ์ธ์๋๋ ค๋ฉด ํฐ๋ฐ์ดํ ๋ง๊ณ ์ค๊ดํธ ์ฌ์ฉ
sub = {this.state.subject.sub}>
</Subject>
<TOC data={this.state.contents}></TOC>
<Content title = "HTML" desc = "์ด๊ฒ๋๋ค..์ ๊ธฐํ๋ค"></Content>
</div>
);
}
}
์ฌ๋ฌ ๊ฐ์ elements๋ฅผ ์๋์ผ๋ก ์์ฑํ๋ ๊ฒฝ์ฐ (Warning: Each Child in a list should have a unique "key" prop.)
class TOC extends Component {
render() {
var lists = [];
var data = this.props.data;
var i =0;
//์์๋ก element๋ฅผ ์์ฑํ๋ ๊ณผ์
while(i < data.length){
//react๊ฐ ๋ด๋ถ์ ์ผ๋ก ๊ตฌ๋ถํ ์ ์๋ ์ฅ์น์ธ key๋ฅผ ํ์๋กํจ.
lists.push(<li key={data[i].id}><a href = {"/content/"+data[i].id}>{data[i].title}</a></li>);
i = i+1;
}
return (
<nav>
<ul>
{lists}
</ul>
</nav>
);
}
}
ํด๋น ์ปดํฌ๋ํธ์ state ๊ฐ์ด ๋ฐ๋๋ฉด ๊ทธ state๋ฅผ ๊ฐ์ง๊ณ ์๋ ์ปดํฌ๋ํธ์ renderํจ์๊ฐ ์ฌํธ์ถ๋จ. (์๋ ์ด๋ฒคํธ์์ ์ด ํน์ง์ ํ์ฉํจ.)
ํด๋ฆญํ์ ๋ ๋ณํ๋ฅผ ์ฃผ๊ณ ์ถ์ ๊ฒฝ์ฐ onClick ์์ ํจ์๋ฅผ ๋ฃ์ด ์ํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
<header>
<h1><a href = "/" onClick={function(e){
e.preventDefault(); //ํ์ด์ง ์ ํ ๋ง๊ธฐ : a ํ๊ทธ์ ๊ธฐ๋ณธ์ ์ธ ๋์ ๋ฐฉ๋ฒ์ ๊ธ์ง
this.setState({
mode: 'welcome'
});
}, bind(this)}>{this.state.subject.title}</a></h1>
</header>
์ด๋ฏธ ์ปดํฌ๋ํธ ์์ฑ์ด ๋๋ ํ์ ๋์ ์ผ๋ก state ๊ฐ์ ๋ฐ๊พธ๊ณ ์ ํ ๋๋ this.state.์ด์ฉ๊ตฌ = '์ด์ฉ๊ตฌ'๋ก ๋ฐ๊พธ๋ฉด ์๋๊ธฐ ๋๋ฌธ์ setState ์ฌ์ฉ
this.state.mode = 'welcome'์ผ๋ก ํ๋ฉด ๋ฆฌ์กํธ์์ state๊ฐ ๋ฐ๋์๋ค๋ ๊ฒ์ ์ธ์ํ์ง ๋ชปํด์ render๊ฐ ํธ์ถ๋์ง ์์
render ํจ์ ์์์ this๋ ๊ทธ ํด๋น ์ปดํฌ๋ํธ ๊ทธ ์์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋๋ฐ, function ์์์์ this๋ ์๋ฌด ๊ฐ๋ ๊ฐ๋ฆฌํค์ง ์๋๋ค.(undefined)
function ๋ด๋ถ์์ ํน์ ์ปดํฌ๋ํธ๋ฅผ this๋ก ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐฉ๋ฒ ์ค ํ๋๊ฐ bind ํจ์์ด๋ค.
var obj = {'name' : '์ด๋ฆ'}
function bindTest() {
console.log(this.name);
}
var bindTest2 = bindTest.bind(obj);
ํ ๊ฒฝ์ฐ bind ํจ์์ ์ํด obj๊ฐ bindTest()์ this๊ฐ ๋๋ ์๋ฆฌ.
cf) ํฅ๋ฏธ๋ก์ด ์ : bind(a, b)๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ b์ ๊ฐ์ด ํด๋น function์ ์ฒซ ๋ฒ์งธ ์ธ์ ๊ฐ์ ๋ค์ด๊ฐ๋ค.
data-id = {data[i].id}
onClick = {function(e){
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}, bind(this)
}
onClick = {function(id, e){
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}, bind(this, data[i].id)
}
์์ ๋ ํจ์๋ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค.
App.js์์ ์ ์ํ onChangePage๋ผ๋ ์ด๋ฒคํธ ํจ์๋ฅผ ๋ค๋ฅธ js ํ์ผ์์ ์ ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ props๋ฅผ ์ฌ์ฉํด ๊ฐ์ ธ์ค๋ฉด ๋๋ค.
1) App.js
<Subject
title = {this.state.subject.title}
sub={this.state.subject.sub}
onChangePage = {function(){
this.setState({
mode: 'welcome'
});
}.bind(this)}
>
</Subject>
2) Subject.js
onClick = {function(e){
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}
}
๋ฌด์์ด ํด๋ฆญ๋๋์ ๋ฐ๋ผ ๋ํ๋๋ ๋ด์ฉ์ด ๋ฐ๋๋ ํ์ด์ง์ฌ์ ํด๋ฆญ๋๋ ์์์ id ๊ฐ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ e.target.dataset.id๋ฅผ ์ฌ์ฉํ๋ค.
1) onSubmit ์ด๋ฒคํธ์์ e.target์ ์ฌ์ฉํด ์
๋ ฅ๋ฐ์ ๊ฐ์ props๋ก ๋ณด๋
<form action="/create_process" method="post"
onSubmit={function(){
e.preventDefault();
this.props.onSubmit(
e.target.title.value,
e.target.desc.value
);
}.bind(this)}
>
2) App.js์์๋ onSubmit ์ด๋ฒคํธ์ e.target.title.value์ e.target.desc.value๋ฅผ ์ธ์๋ก ๋ฐ์์ state ๋ณ๊ฒฝ
_article = <CreateContent onSubmit={function(_title, _desc){
// add content to this.state.contents
this.max_content_id = this.max_content_id+1;
var _content = this.state.contents.concat(
{id:this.max_content_id, title:_title, desc:_desc}
)
this.setState({
contents:_content
});
}.bind(this)}></CreateContent>
์๋ก ์ ๋ ฅ๋ฐ์ ์์๋ค์ concat์ผ๋ก ์ถ๊ฐํด์ ํ๋ฉด์ ๋ณด์ฌ์ค.
render ์ด์ ์ ์คํ๋๋ ํจ์๋ก, ์ฌ๊ธฐ์ '๋ณํ'๋ฅผ ๊ฐ์งํ๊ธฐ ์ํด์ ์๋ณธ์ ๋ฐ๊พธ์ง ์๊ณ (push) ์ฌ๋ณธ์ ์์ ํ๋ค.(concat)
//render ์ด์ ์ ์คํ๋๋ ํจ์
shouldComponentUpdate(newProps, newState){ //์๋กญ๊ฒ ๋ฐ๋ ๊ฐ๊ณผ ์ด์ ๊ฐ์ ์ ๊ทผํ ์ ์๋ค.
if(this.props.data === newProps.data){
return false;
}else{
return true;//return๊ฐ์ด true์ด๋ฉด render๊ฐ ํธ์ถ๋๊ณ , false๋ฉด ํธ์ถํ์ง ์๋๋ค.
}
}
Array.from()์ ์ฌ์ฉํด ์ฌ๋ณธ์ ๋ง๋ ํ pushํ๋ ๊ฒ๋ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ผ ์ ์๋ค.
์ค๋ณตํด์ ์ฌ์ฉ๋๋ ํจ์๋ค์ ๋ฐ๋ก ์ ์ํด๋๊ฑฐ๋ ๋ฏธ๋ฆฌ ์ด๊ธฐํํด๋๋ฉด ์ฝ๋๊ฐ ๊น๋ํด์ง๋ค.
constructor(props){
super(props);
this.state = {
title:this.props.data.title
}
this.inputFormHandler = this.inputFormHandler.bind(this);
}
inputFormHandler(e){
this.setState({[e.target.name]:e.target.value});
}
์ด๋ ๊ฒ ์์ ๋ฏธ๋ฆฌ ์ ์ํด๋๋ฉด render์์ ์๋์ฒ๋ผ ์ฌ์ฉ ๊ฐ๋ฅ
<p>
<input
type="text"
name="title"
placeholder="title"
value = {this.props.data.title}
onChange={this.inputFormHandler}
>
</input>
</p>