이벤트 만들기
해당 컴포넌트가 아닌 하위 컴포넌트에서 발생한 이벤트를 이용해 상위 컴포넌트의 State를 변화시키려면 어떻게 해야할까?
props로 이벤트 전달 -> 하위 컴포넌트 클릭시 이벤트 실행하도록 한다 -> 이벤트 통해 상위컴포넌트의 state변경 -> render -> 하위 컴포넌트에 변경된 props전달 -> 애플리케이션 동적 변화
Subject라는 Component에 onChangePage()라는 이벤트를 만든다.
Subject안의 a태그를 클릭해 이벤트가 발생했을 때, props를 통해 전달된 이벤트가 실행되도록 한다.
1
2
3
4
5
6
7
8
|
// App.js
<TOC
onChangePage={function(){
this.setState({
mode: "read"
});
}.bind(this)}
data={this.state.contents}></TOC>
|
cs |
일단 state.mode만 바꾸는 함수를 만들고, TOC.js에서 a태그와 연결한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// TOC.js
lists.push(
<li key={data[i].id}>
<a
onClick={function(e){
e.preventDefault();
this.props.onChangePage();
// 여기에서 어떻게 App.js으로
// 선택된 a(li)에 대한 정보를 전달할 것인가?
}.bind(this)}
href={"/content/"+data[i].id}
>{data[i].title}</a>
</li>)
i = i + 1;
|
cs |
a의 onClick 함수 안에서 선택된 a에 대한 정보가 상위 컴포넌트에 전달되어야 한다.
그래야 상위 컴포넌트(App)에서 setState()를 통해 state를 변화시키고, render()를 실행시킬 수 있다.
정보 전달을 위해 event 를 이용한다. event는 target이라는 속성을 가진다. event(여기에서는 클릭)가 일어난 대상에 대한 정보를 가지고 있다.
event.target을 통해 쉽게 정보를 가져오기 위해 a태그에 data-id속성을 만들어주고, 그 정보를 this.props.onChangePage()의 매개변수로 전달한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// TOC.js
lists.push(
<li key={data[i].id}>
<a
data-id={data[i].id}
onClick={function(e){
e.preventDefault();
// a 태그의 data-id속성값을 전달한다(=data[i].id값)
this.props.onChangePage(e.target.dataset.id);
}.bind(this)}
href={"/content/"+data[i].id}
>{data[i].title}</a>
</li>)
i = i + 1;
|
cs |
App.js에서 TOC의 onChangePage 함수도 매개변수를 처리할 수 있도록 바꿔준다.
state에 선택된 li의 정보를 저장하는 content_id를 만들어주고, TOC의 onChangePage에서 state를 바꿔주도록 설정한다.
1
2
3
4
5
6
7
8
|
// App.js
contsructor(props){
super(props);
this.state = {
...
content_id: null, // 초기값: null
...
}
|
cs |
1
2
3
4
5
6
7
8
9
|
// App.js
<TOC
onChangePage={function(id){
this.setState({
mode: "read",
content_id: Number(id)
});
}.bind(this)}
data={this.state.contents}></TOC>
|
cs |
function(id) 로 전달받은 변수를 id에 저장하고, setState에서 content_id를 전달받은 id로 바꿔준다.
data-id속성으로 만들어진 속성의 값은 string형태이므로 Number(id)를 통해 number 형으로 바꿔준다.
setState()를 통해 state를 변경시키면 render함수가 호출되어 변경된 state를 참고해 다시 페이지를 구성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// App.js
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.content_id) {
_title = data.title;
_desc = data.desc;
break;
}
i = i + 1;
}
}
}
|
cs |
render() 함수가 실행될 때, this.state.mode === "read"이면 while문을 사용해 전달받은 this.state.content_id와 같은 id를 가지는 data를 찾는다.
이렇게 찾은 title과 desc는 _title과 _desc에 저장되어 Content 컴포넌트에 전달된다.
1
2
|
// App.js
<Content title={_title} desc={_desc}></Content>
|
cs |
결과적으로 TOC의 li를 선택하면, content_id와 Content의 내용이 바뀐다.
TOC에서 선택한 a의 id가 전달되는 경로를 보면 아래와 같다.
위는 TOC.js의 코드이고, 아래는 App.js의 코드이다.
*참고사항
render()에서
_title = this.state.contents[this.state.content_id].title;
_desc = this.state.contents[this.state.content_id].desc;
으로 정보를 가져오지 않는 이유는 Contents 안의 내용들이 제거/수정된다면 index로 접근하는 경우,
기대하는 결과를 만들 수 없는 상황이 나올 수 있기 때문이다.
참고한 페이지
생활코딩 react 강의
17.1 컴포넌트 이벤트 만들기
17.2 컴포넌트 이벤트 만들기
17.3 컴포넌트 이벤트 만들기
https://www.youtube.com/watch?v=NFR7vDArVlY&list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi&index=25
'React' 카테고리의 다른 글
생활코딩 React 강의 (9) - update 구현 (0) | 2021.09.13 |
---|---|
생활코딩 React 강의 (8) - create 구현 (0) | 2021.09.09 |
생활코딩 React 강의 (6) - 이벤트 (0) | 2021.09.06 |
생활코딩 React 강의 (5) - State (0) | 2021.09.03 |
생활코딩 React 강의 (4) - React Developer Tools (0) | 2021.09.03 |