React

생활코딩 React 강의 (7) - 컴포넌트 이벤트 만들기

joy_lee 2021. 9. 8. 14:27

이벤트 만들기

해당 컴포넌트가 아닌 하위 컴포넌트에서 발생한 이벤트를 이용해 상위 컴포넌트의 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