생활 코딩 리액트 강의 <https://www.youtube.com/playlist?list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi>
나만의 태그에 이벤트를 만들어서 태그/컴포넌트를 생산해보기
(리액트 스터디 4일 차의(리액트 스터디 4일 차의 응용)
하려는 것1:
App.js의 subject 컴포넌트에 onChagePage라는 이벤트를 내가 만듦.
이 이벤트에 alert창 뜨게 하는 함수를 설치
그 이벤트가 발생되었을 때, props로 전달된 onChangePage 함수를 호출하면 됨.
여기까지 해서, 리로딩 방지하고 alert창 잘 뜨면 내가 만든 이벤트에 setState 이용해서 state 바꾸는 함수로 수정
전:
App.js- header 태그 안의 코드는 원래 Subject.js에 있던 코드. 근데 쉽게 이해하기 위해 Subject의 코드를 바깥으로(app.js) 옮겨놨었을 뿐
후:
header 태그 주석 처리하고, 이전에 작업했던 subject 컴포넌트를 살림. 이제 이 컴포넌트에 이벤트를 설치할 것임. "사용자들아 내가 만든
이벤트를 쓰고 싶으면 onChangePage 써
"
즉, subject 컴포넌트는 onChangePage라고 하는 이벤트가 있어서, 이 컴포넌트 안에서 링크를 클릭했을 때 이벤트에 설치한 함수를 호출하도록 만듦. (사용자가 함수를 설치하는 거임)
onChangePage는 props형태로 subject에 전달될 것임.
->Subject.js에서 onChangePage를 호출할 때 this.props.onChangePage();라고 해주면 됨
하려는 것2:
mode를 read로 바꾸고, 목록들을 클릭하면 밑에 해당 description 출력하기
html, css, javascript 버튼 클릭하면 mode를 read로 바꾸는 것을 쉽게 됨.
Subject.js 바꾼 거 참고해서 코드 수정하면 됨
toc.js에서는 a href 태그에서 onclick에 함수 function(e) 만들어서 거기에 preventDefault랑 props로 내가 만든 함수 호출하게 바꿔주고
app.js 에서는 onChangeDesc로 내가 이벤트 만들어주고 mode 바꾸는 setState 코드 넣어주면 됨.
문제점: 각 버튼마다 다른 description이 나와야 되는데 다 똑같은 내용만 출력됨
해결책 1:
(App.js에서)
- selected_content_id라는 state값을 새로 준다
- mode가 read일 때 부분-> while문 돌려서 selected_content_id랑 data .id랑 같을지 비교해서 _title, _desc 값 집어넣게 바꾸기
- TOC 컴포넌트 부분에 onChangeDesc 이벤트 함수가 실행될 때 mode도 바뀌고, selected_content_id도 바꾸게
- 근데 selected_content_id는 TOC.js에서 인자로 보내주는 값으로 지정할 것
(TOC.js에서)
- 클릭한 id를 얻기 위해 새로운 속성 data-id를 추가
- onChangeDesc 호출할 때 앞에서 추가한 속성을 이용해서 e.target.dataset.id를 인자로 넘김.
target은 a태그를 가리킴. data-라는 접두사로 시작되는 속성은 dataset이라고 하는 특수한 것을 통해 접근할 수 있음. 그리고 접두사 뒤에 붙어 있는 id는 data[i].id가 가지고 있는 값임.
이렇게 얻은 id를 app.js에서 내가 정의한 이벤트 함수의 인자로 보내주게 함. 근데 인자로 보내는 id가 char라 app.js에서 int형으로 바꾸어 주어야 함
해당 코드
App.js
import React, { Component} from 'react';
import TOC from "./components/TOC"; //TOC를 App.js에서 쓰기위한 import문
import Subject from "./components/Subject";
import Content from "./components/Content";
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'read',//welcome 페이지, read 페이지 구분 //밑에 if문에서 mode검사할 때 welcome 철자/대소문자 오타 조심
selected_content_id:2, // 선택된 content를 출력하기 위한 변
subject:{title:'web', sub:'world wide web'},
welcome:{title:'Welcome', desc:'Hello, React'}, //welcome mode일 때 content에 표시될 텍스트 지정
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'}
]
}
}
render() {
console.log('App render'); //render 호출되는지 로그 찍어보기
var _title, _desc = null;
if(this.state.mode === 'welcome') { //=== 3개인 거 오타 조심
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
} 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;
}
}
return (
<div className="App">
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function(){
{/*alert('hihihi');*/}
this.setState({
mode:'welcome'
})
}.bind(this)}
>
</Subject>
<TOC
data={this.state.contents}
onChangeDesc={function(id) {
this.setState({
mode:'read',
selected_content_id:Number(id)
})
}.bind(this)}
>
</TOC>
<Content title={_title} desc={_desc}></Content>
</div>
);
}
}
export default App;
TOC.js
import React, { Component} from 'react';
//리액트라는 라이브러리에서 컴포넌트라는 클래스를 로딩한 것.
class TOC extends Component {
render(){
console.log('TOC render'); //render 호출되는지 로그 찍어보기
var lists=[];
var data=this.props.data;
var i=0;
while(i<data.length){
lists.push(
<li key={data[i].id}>
<a
href={"/content/"+data[i].id}
data-id={data[i].id} //클릭한 id를 얻기 위해 새로운 속성 추가
onClick={function(e){
e.preventDefault();
this.props.onChangeDesc(e.target.dataset.id);
}.bind(this)}>
{data[i].title}</a>
</li>);
i=i+1;
}
return(
<nav>
<ul>
{lists}
</ul>
</nav>
);
}
}
export default TOC;
//이 export문을 써줌으로써 TOC라는 클래스를 다른 파일이 가져다 쓸 수 있음.
- 상위 컴포넌트(app.js)가 하위 컴포넌트(subject, content, toc.js)로 값을 전달할 때 props를 통해 전달
- 하위 컴포넌트가 상위 컴포넌트의 값을 바꾸고 싶을 때 이벤트를 통해서 함
ex) 버튼 클릭했을 때 mode와 selected_content_id를 바꾸고 싶은 경우 (toc가 app의 무언가를 바꾸고 싶어 하는 경우)
->이벤트를 구현해서, 이벤트가 트리거 됐을 때 상위 컴포넌트의 state 값을 호출하는 것을 통해서 state 값을 바꿀 수 있음
App.js의 일부분
<TOC
data={this.state.contents}
onChangeDesc={function(id) {
this.setState({
mode:'read',
selected_content_id:Number(id)
})
}.bind(this)}
>
</TOC>
- Redux
위처럼 데이터를 분산해서 보관하는 것이 아닌 하나의 저장소에 저장. 저장소의 값이 변경되면 이와 관련된 모든 컴포넌트의 값도 변경되게 하는 테크닉
'JAVASCRIPT > React' 카테고리의 다른 글
[생활코딩 React 강의] Immutable이란? (concat, shouldComponentUpdate, Array.from, Object.assign) (0) | 2019.08.20 |
---|---|
[생활코딩 React 강의 4] CRUD 중 Create 구현하기 (0) | 2019.07.01 |
[생활코딩 React 강의 4] 이벤트 설치해보기 (0) | 2019.05.18 |
[생활코딩 React 강의 3] State란? state 사용해보기 (0) | 2019.04.26 |
[생활코딩 React 강의2] 컴포넌트 만들기, Props, 컴포넌트 파일로 쪼개기 (0) | 2019.04.26 |
Comments