17.1강 컴포넌트 이벤트 만들기
이벤트의 생산자가 되어보자,
<header>
<h1><a href="/" onClick={function(e){
console.log(e);
e.preventDefault();
this.setState({
mode: 'welcome'
});
}.bind(this)}>{this.state.subject.title}</a></h1>
{this.state.subject.sub}
</header>
a태그를 클릭했 을 때, onClick이라는 이벤트에 설채 해놓은 사용자정의 함수가
호출 되면서 우리는 app컴퍼넌트의 mode의 값을 welcome으로 바꾸는 코드
그런데 이 header의 코드는 원래 subject.js 안에 있던 코드이다.
그런데 수업을 단순하게 하기 위해서 이 파일을 주석처리하고 내용을
저렇게 header안에 옮겨놨다. 이해하기가 쉬워서
이제 이 바깥 쪽에 있는 코드를 주석화하고 본 코드를 살려보자.
우리는 subject라고 하는 저 컴퍼넌트의 제작자 또는 생산자 입장에서
저것을 사용하려고 하는 이용자들에게 이렇게 얘기한다.
만약 이 서브젝트라는 컴퍼넌트를 사용할 때, 사용자가 여기 있는 이 링크를 클릭했을
때 어떠한 일이 일어나게 하고 싶다면, 즉, 이벤트를 설치하고 싶다면
onChangePage 라는 이벤트를 쓰세요.
이벤트의 함수를 설치해 놓으면 이 a태크가 클릭 되었을 때 우리가 설치한
그 함수를 실행해 드릴게요.
우리가 만들려고 하는 서브젝트라고 하는 이 컴퍼넌트는 onChangePage라는
이벤트가 있어서 이 컴퍼넌트 안에서 링크를 클릭 했을 때, 이 이벤트의
설치한 함수를 호출하도록 만들려고 하는 것
사용자들은 어떻게 할까?
우리가 만든 이 Subject 컴퍼넌트는 페이지가 바뀌었을 때 여기를 누군가 클릭했을 때
사용자가 설치한 이 컴퍼넌트의 사용자가 설치한 이 함수를 호출해 주기만 하면 된다.
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function(){
alert('hihihi');
}.bind(this)}
>
어떻게 할까?
onChangePage라고 하는 이 함수는 어떤 형태로 Subject에 전달 될까?
'props' 이다
여기에 a태그를 onClikc했을 때, 함수가 실행이 이렇게 된다.
onClick={function(){}.bind(this)
그리고 실행 됐을 때 첫 번째 인자로 이벤트 객체(e)가 전달되는데 그 객체의
e.preventDefault(); 라고 하는 것을 호출해서 링크를 클릭했을 때 페이지가
바뀌는 것을 막는 것.
그 다음, 이 Subject 컴퍼넌트의 onChangePage로 함수가 전달 된다.
<header>
<h1><a href="/" onClick={
function(e){
e.preventDefault();
this.props.onChangePage()
}.bind(this)
}
>
{this.props.title}</a></h1>
{this.props.sub}
</header>
그 함수를 여기에서 호출해주면 된다.
this.props.onChangePage
=>app.js의
function(){
alert('hihihi');
}.bind(this)
정리
우리는 Subject라고 하는 컴퍼넌트의 onChangePage 이벤트를 만들었다.
<Subject
title={this.state.subject.title}
sub={this.state.subject.sub}
onChangePage={function(){
alert('hihihi');
}.bind(this)}
>
그리고 저 이벤트에다가 이렇게 함수를 설치해 주면
onChangePage={function(){
alert('hihihi');
}.bind(this)}
그 이벤트가 발생되었을 때 Subject.js에 있는
<h1><a href="/" onClick={
function(e){
e.preventDefault();
this.props.onChangePage()
}.bind(this)
}
>
링크(WEB)를 클릭했을 때, 우리는 props로 전달된 onChangePage라는 함수를
호출하면 된다. 그렇게 해서 경고창hihihi가 뜬 것이다.
만약에 hihi를
onChangePage={function(){
this.setState({mode:'welcome'});
}.bind(this)}
이렇게 바꾸어주면
WEB을 눌렀을 때 State의 mode를 welcome으로 바꾸는 작업을 한다.
App이라고하는 컴퍼넌트의 mode의 갑싱 "read" -> "welcome"으로 바뀌고
화면이 잘 변경되었다. 우리는 이벤트 소비자에서 벗어나서 생산자가 되었다.
Q.
왜 밑에선 state 말고 props로 이벤트를 부르는걸까요..?
A.
App.js에서 하위컴포넌트인 Subject 클래스를 사용할때 Subject의 props를 onChangePage로 입력을 하였어요~
추가적으로 부모클래스에서 자식클래스에게 값을 전달하기 위해 state를 사용하고, 그 state를 props를 통해 전달을 합니다.
17.2강 컴포넌트 이벤트 만들기
Subect라고 하는 내가 만든 컴퍼넌트에 onChangePage라고 하는 이벤트를
우리가 만들어서 사용자에게 제공하였다.
이번에는 글 목록을 클릭했을 때 App이라고 하는 컴퍼넌트에 state의 mode를
read로 바꿀 것이다. 즉, 우리가 클릭한 것에 해당되는 컨텐트가 본문에 나오게 해볼 것이다.
App.js의 TOC라고 하는 컴퍼넌트에 똑같은 이름의 이벤트를 만들어보자
<TOC
onChangePage={function(){
alert('hi');
}.bind(this)}
data={this.state.contents}>
</TOC>
이러기 위해선 onChangePage라고 하는 props를 TOC.js 안에서 받아야한다.
<a
href={"/content/"+data[i].id}
onClick={function(e){
e.preventDefault();
this.props.onChangePage();
}.bind(this)}
>{data[i].title}</a>
</li>);
onClick을 했을 때 function이 실행이 되고, 클릭했을 때 페이지가 다른페이지로 eload가
안 되기 하기 위해서는, 이벤트 객체(e)를 받아서 객체에
e.preventDefault 라는 함수를 실행하면 된다.
여기서 this의 props.에 onChangPage 라고 하는 저 props를 실행하면
App.js의 TOC의 함수가 실행이 되면서 경고창이 뜬다.
자 이제,
APP 컴퍼넌트의 State 중 mode 값을 read로 바꿔주면 된다.
<TOC
onChangePage={function(){
this.setState({mode:'read'});
}.bind(this)}
data={this.state.contents}>
</TOC>
17.3강 컴포넌트 이벤트 만들기
글 몰록에서 선택한 컨텐트 (HTML, CSS, JS)가
밑의 본문 HTML 쪽에 표시되게 해보려고 한다.
App의 state에다가 selected-content-id
이름을 줘서 윌가 현재 활성화된 선택된 컨텐트를 여기에다가 표시할 것이다.
그러면 그 값을 바탕으로 해서 이 컨텐트라고 하는 저 객체이 있는 id 값 중에
그 값과 일치하는 selected 컨텐트 id값과 일치하는 것을 본문에 표시하게 할 것이다.
class App extends Component {
constructor(props){
super(props);
this.state = {
mode:'read',
selected_content_id:2,
subject:{title:'WEB', sub:'World Wid Web!'},
welcome:{title:'Welcome', desc:'Hello, React!!'},
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'}
]
}
}
이 컨텐트를 바탕으로 3개의 글 몰록 중 누가 본문에 나올 것인가를 지정을 하는데[
어디서 하면 되냐면
밑에 있는 render에 mode가 read 일 때, 이 부분에서 하면 된다.
render() {
console.log('App render');
var _title, _desc = null;
if(this.state.mode === 'welcome'){
_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;
}
}
현재 순번에 해당되는 컨텐트를 var = data 라고 하고
만약에 data의 id 값이 this.state의 selected컨텐트 id값이 일치하는 것이 발견된다면
title이 description 될 자격이 있다.
강제로 i문을 내버리는 코드인 break를 쓰면 break가 실행되는 순간에 조건문이
끝나고, 조건문 바깥 쪽에 있는 코드들이 실행되기 시작한다.
페이지가 selected_content_id 값에 따라 바뀌는 것을 확인 했으면
이제는 뭘 해야하나?
TOC가 저기 있는 리스트니까, 저 리스트에 onChangepage 이벤트가 발생했을 때
우리는 this.setState를 통해서 모두의 값과 함께 selected_content_id 에 값을
0이라고 되어있는 부분의 값으로 해주면 된다.
<TOC
onChangePage={function(){
this.setState({mode:'read',
selected_content_id:0
});
}.bind(this)}
data={this.state.contents}>
</TOC>
App.js의 TOC onChangepage 이벤트를 실행시키는 부분은
TOC.js에서 onClick을 했을 때 바로 이 props를 실행 시키는 것을 통해서 이 함수를
실행해주는 것이다. TOC가 App.js에 이쓴 함수를 실행시키는 것.
즉, 그것을 실행할 떄 인자로 우리가 클릭한 항목의 id값을 주면 된다.
이것을 하는 방법 2가지
data-id={data[i].id} 이런 속성을 주는 것이다.
이벤트 객체는 target 이라는 속성이 있다. 이 target이라는 속성은 그 이벤트가 발생한
태그 즉 a태그를 가리킨다. 그래서 우리가 그 이벤트 함수 내에서 e.target 이라고 하면
저 이벤트가 소재하고 있는 태그인 a태그를 가리킨다. 우리는 요걸 통해서
a태그를 알아냈으면, 그 a 태그를 갖고 있는 data-id 값에 접촉할 수 있게 된 것.
TOC
<a
href={"/content/"+data[i].id}
data-id={data[i].id}
onClick={function(e){
e.target
debugger;
e.preventDefault();
this.props.onChangePage();
}.bind(this)}
>
id 가 2인데 이 값이 data[i].id 여기에 들어있는 값이다.
알아낸 정보를 onChangePage 함수를 호출하는 코드에 인자로 넣어 준다.
App의 onChangePage에서 id라는 매개변수를 주고 실행하면
State에서 selected_content_id값이 변하는 것을 볼 수 있다.
숫자는 바뀌는데 안되는 이유는 그 값은 문자열이고
content의 id는 숫자이다. 데이터 형식이 다르다.
문자를 숫자로 바꿔주는 자바 스크립트의 명령중 하나인 Number로 감싸준다.
웹을 클릭하면 mode가 welcome이 되고 리스트 컨텐트를 클릭하면 read가 되어서
그것에 해당되는 selected_content_id 가 바뀌기 때문에 내용도 같이 잘 바뀐다.
App
<TOC
onChangePage={function(id){
this.setState({mode:'read',
selected_content_id:Number(id)
});
}.bind(this)}
data={this.state.contents}>
</TOC>
TOC
(<li key={data[i].id}>
<a
href={"/content/"+data[i].id}
data-id={data[i].id}
onClick={function(e){
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}.bind(this)}
>{data[i].title}</a>
</li>);
정리
속성을 이용하는 방법
onClick이라고 하는 저 속성은 저 이벤트를 실행시킬 때 우리가
e의 target의 dataset의 id를 통해서 추출 했는데
data값의 이름에 따라서 밑의 id도 달라진다.
data-id={data[i].id}
<a
onClick={function(e){
e.preventDefault();
this.props.onChangePage(e.target.dataset.id);
}.bind(this)}
>
속성을 이용하지 않고 하는 방법
bind의 두 번 째 인자로 data[i].id 라는 값을 주면 이 bind는 두 번째 인자로 들어온
이 값을 이 함수의 첫 번쨰 매개 변수의 값으로 넣어준다. 그리고 기존에 있었던 것은
뒤로 한 칸씩 밀리는 것. 이런식으로 처리해도 똑같이 적용된다.
function(id, e){
e.preventDefault();
this.props.onChangePage(id);
}.bind(this, data[i], id)}
#이번 강의를 이해하기 위해 가장 중요한 부분은 첫 1분동안 나오는 내용인 것 같습니다. 왜 'selected-content-id'란 값을 state에 추가했는지, 이 코드의 역할이 무엇인지를 분명히 강사님은 첫 부분에 말씀해 주셨지만 강의가 끝나고 나면 기억에 남지 않습니다. 후반부에 나오는 target의 기능, data-id의 역할 등을 쫓아가다보면 앞의 내용이 없어져버리거든요. 후에 복습을 하려하면 target의 기능, data-id의 역할은 이해하겠는데 왜 이게 필요한지를 모르기 때문에 붕 뜬 기분이 들고 막막해집니다. 즉, 이 코드를 통해서 만들고자 하는 기능을 명확히하고 그 시발점을 어디서부터 가르는지를 정확히 인지하고 계신다면 target의 기능이나 data-id의 역할은 부수적인거라고 생각합니다.
#// 1. data-id: // evenet 객체는 target이라는 속성이 있고, // target은 이벤트가 발생한 태그 a태그를 가리킵니다. // event 함수 내에서 e.target은 <a>태그를 가리킨다. // 그러하면, <a>태그의 속성에 접근 할 수 있다. // data- 접두사로 시작되는 속성은 dataset이라는 속성으로 접근 할 수 있다. // e.target.dataset.id 로 data-id를 찾을 수 있다. // 2. bind(this, id) // bind(this, 두번째 인자)를 주게 되면, // function(e) → function(id, e)가 되면서, 파라미터가 하나씩 밀리게 된다.
Q.
TOC.js 에서, data-id = {data[i].id}가 아니라 data_id로 했는데 작동 안되는데 이유가 무엇인가요? 변수명에 -를 사용하면 뭔가 규칙이 있는거 같은데 설명해주실분 ㅠㅠ
A.
다른 개념이에요 저도 정확히 알고 있는건 아니고... 그냥 대략적으로 이해하고 설명 드리는거니 제 댓글 읽으시고 나중에 꼭 타 강의영상, 강의 글 참고 부탁드립니다.
html의 태그들 (<a> <input> 등등등) 에는 여러가지 attribute 즉 속성을 넣을 수 있습니다. 강의에 나오는 a태그로 예를 들면 꺽쇠 안에 들어가는 href, onClick 가 그것입니다. (임의로 원하는 속성을 만들 수 도있습니다! 'test', 'babo' 저희 맘대루요.) 그중에는 data라는 속성이 있습니다. 이 속성은 페이지를 해석 할 때 dataset 이라는 걸로 해석하는데요 일종의 data보따리처럼 다루는 것 같습니다.
선생님이 하신 건 data라는 큰 보따리에 id라는 작은 보따리를 만들어서 값을 넣는 과정이라고 보시면 되겠습니다. 그러한 과정을 하기위한 규칙은 data 뒤에 _(언더바) 가 아닌 -(하이픈, 대시)를 붙이고 작은 보따리 이름을 붙이는 것입니다. ex) data-id, data-test, data-babo
작성자님께서 하신 건 dataset을 이용하는 것이 아닌 data_id라는 임의의 속성을 만드신 겁니다. 그래서 e.target.dataset.id (a태그의 dataset의 id)를 찾느 코드는 안먹히는 거구요. 만약 data_id로 작동을 원하신다면 단순하게 e.target.data_id라고 하면 '아마' 작동 할 겁니다.
'[자기계발] > 유튜브로 코딩배우기' 카테고리의 다른 글
[생활코딩] React 강의 완강 - 20~21강 update 구현 (0) | 2021.05.11 |
---|---|
[생활코딩]React 강의-4 18강~19강 create (0) | 2021.05.10 |
CS 전공을 해야할까? 개발자가 되기 위해 대학을 나와야할까? (0) | 2021.04.21 |
[생활코딩]React 강의-2 15~16강 State, props, bind 소개 (0) | 2021.04.19 |
[생활코딩] React 강의-1 1~14강 React 소개 (0) | 2021.04.06 |