1. 이벤트 리스닝하기와 반응하기
- 카운터 예제로 한번 알아보자



- 노란색 화면에 count 숫자와 버튼 하나가 생성된것을 확인할 수 있다. 지금은 + 버튼을 누르더래도 아직 아무 변화가 생기지 않는다.
2. 버튼 작동시키기
- 버튼을 눌렀을때 count를 1씩 증가 시켜야 한다.
1) 버튼 클릭 이벤트를 리스닝 한다
2) 클릭에 반응해 카운더가 의존하는 this.state.count 속성의 값을 증가시킬 이벤트 헨들러를 구현한다.

- onClick 을 눌렀을때 increase 함수를 호출하라는 의미이다
- increase 함수 즉 이벤트 핸들러를 구현해 보자
1) increase 함수를 정의한 후
2) increase 함수에 대해서 constructor에서 바인딩 해준다

== 카운터 최종코드 ==
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>From Data to UI</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style>
#container {
padding : 50;
background-color: #fff;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
class Counter extends React.Component{
render(){
var textStyle = {
fontSize : 72,
fontFamily : "sans-serif",
color : "#333",
fontWeight : "bold"
}
return(
<div style={textStyle}>
{this.props.display}
</div>
)
}
}
class CounterParent extends React.Component{
constructor(props){
super(props);
this.state = {
count : 0
}
this.increase = this.increase.bind(this);
}
increase(e){
this.setState({
count : this.state.count + 1
});
}
render(){
var backgroundStyle = {
padding : 50,
backgroundColor : "#ffc53a",
width : 250,
height : 100,
borderRadius : 10,
textAlign : "center"
}
var buttonStyle = {
fontSize : "1em",
width : 30,
height : 30,
fontFamily : "sans-serif",
color : "#333",
fontWeight : "bold",
lineHeight : "3px"
}
return (
<div style={backgroundStyle}>
<Counter display={this.state.count}/>
<button onClick={this.increase} style={buttonStyle}>+</button>
</div>
)
}
}
ReactDOM.render(
<div>
<CounterParent />
</div>
, document.querySelector("#container")
);
</script>
</body>
</html>
3. 이벤트 속성
- 이벤트는 이벤트 핸들러에 인자로 전달된다. 예들 들어 마우스 이벤트 라면 그 이벤트 객체와 인자의 타입은 MouseEvent다. MouseEvent 객체를 통해서 클릭 여부나 , 클릭당시 포인터의 위치, 마우스의 특정 정보에 접근할 수 있다.
- 각 이벤트는 그 종류마다 자신만의 소성들을 포함하며, 이벤트 핸들러에서 그 속성에 접근 할 수 있다.
1) 합성 이벤트
> 리액트에서는 앞서 onClick에서 했던것 처럼 JSX에서 이벤트를 지정하는 경우 DOM이벤트를 직접 다루지 않는다.
> 그 대신 합성 이벤트라고 하는 리액트의 특별한 이벤트 유형인 SyntheticEvent를 다룬다.
> 항상 브라우저의 네이티브 이벤트를 래핑하는 SyntheticEvent 타입을 인자로 받는다.
SyntheticEvent 가 포함하는 속성들 |
boolean bubbles boolean cancleable DOMEventTarget currentTarget boolean defaultPrevented number eventPhase boolean isTrusted DOMEvent nativeEvent void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() DOMEventTarget target number timeStamp string type |
이들의 속성은 매우 직관적이며, 공통적이다. 공통적이지 않는 속성들은 SyntheticEvent가 래핑하는 네이티브 이벤트의 종류에 따라 다르다.
ex) MouseEvent를 래핑하는 SyntheticEvent는 마우스 이벤트에 특정적인 속성들을 갖는다.
> boolean altKey, number button, number buttons, number clientX, number clinetY, boolean ctrlKey, boolean getModifierState(key), boolean metaKey, number pageX, number pageY, DOMEventTarget relatedTarget, number screenX, number screenY, boolean shiftKey 등이 있다.
ex) 마찬 가지로 KeyboardEvent 를 래핑하는 SyntheticEvent 는 다음과 같은 키보드 관련 소성들을 추가로 갖는다
> boolean altKey, number charCode, boolean ctrlKey, boolean getModifierState(key), string key, number keyCode, string locale, number location, boolean metaKey, boolean repeat, boolean shiftKey, number which
결과 적으로 SyntheticEvent를 가지고 평범한 DOM 세계에서 했던 작업을 동일하게 할수 있다는 의미이다.
4. 이벤트 속성 다루기
- 예제를 발전시켜 속성을 다뤄보자, 이전 예제에서 shiftKey를 누르고 +를 누르면 카운터가 10씩 증가하도록 수정해보자
- 합성 이벤트와 그 속성을 사용할때 이슈가 있을 경우 리액트의 SyntheticEvent 문서를 참고하자(https://reactjs.org/docs/events.html)

5. 또 다른 이벤트 처리기법
1) 컴포넌트의 이벤트는 직접 리스닝 할 수 없다.
- 아래의 코드를 보면 <PlusButton> 이라는 새로운 컴포넌트가 있고 해당 + 버튼을 누르면 increase 함수가 호출되야 한다고 생각하는데 PlusButton 을 눌러도 아무 일도 생기지 않는다. 단지 엘리먼트를 리턴할 뿐이다.


- 컴포넌트의 이벤트를 직접 리스닝 할수 없다는 사실이다. 컴포넌트의 이벤트를 리스닝 한다는 건 어떤 의미일까? 다행히 이벤트 핸들러를 속성처럼 다루고 컴포넌트에 전달 할 수 있는 차선책이 있다. 바로 컴포넌트 안에서 DOM 엘리먼트에 이벤트를 할당하고 속성 값으로 이벤트 핸들러를 설정하면된다.
- <PlusButton/> 태그에 clickHandler 라는 핸들러를 설정 한 후
- <PluseButton> return 시에 onClick evnet에 해당 넘겨준 핸들러 값을 적용해주면 된다.

6. 일반 DOM 이벤트의 리스닝
- 모든 DOM 이벤트가 SyntheticEvent에 대응하지는 않는다. 리액트가 인식할수 있는 공식 이벤트가 아닐경우에는 코드가 작동하지 않는다 따라서 이 경우에는 컴포넌트 생명주기 메소드에서 addEventListener를 사용하는 전통적인 방법을 따라야 한다.

7. 이벤트 핸들러 내부의 this
- 리액트에서 이벤트 핸들러 내부의 thjis는 DOM 세계의 경우와 다르다. 리액트가 아닌 세계에서는 이벤트 핸들러안의 this가 이벤트를 발생시킨 엘리먼트를 참조한다. 그러나 리액트 세계에서는 이벤트 핸들러 안의 this는 이벤트를 발생시킨 엘리먼트의 참조가 아니라!!, 그냥 undefined 이다. 지금까지 여러번 봤듯 bind 메소드를 사용해 this를 명시적으로 지정해야 하는 이유가 이때문이다.
리액트는 절대 이벤트 핸들러를 DOM 엘리먼트에 집적 부착하지 않는다. 리액트는 문서 최상위에 있는 하나의 이벤트 핸들러를 사용한다. 이 이벤트 핸들러는 모든 이벤트를 리스닝하며, 이벤트 발생시 적합한 개별 핸들러를 호출하는 책임을 진다.
'dev > React' 카테고리의 다른 글
[React] DOM 엘리먼트 접근 (0) | 2022.12.01 |
---|---|
[REACT] 컴포넌트 생명주기 (0) | 2022.12.01 |
[React] 데이터에서 UI로 (0) | 2022.11.30 |
[React] 상태 다루기 (0) | 2022.11.30 |
[REACT] JSX 특징 (0) | 2022.11.30 |