[리액트를 다루는 기술] 4장 이벤트 핸들링

Bor·2022년 1월 19일
0
post-thumbnail

4.1 리액트의 이벤트 시스템

사용법은 일반 HTML에서 이벤트를 작성하는 것과 비슷한데 주의해야할 몇 가지 사항이 있다.

4.1.1 이벤트를 사용할 때 주의 사항

  • 1) 이벤트 이름은 카멜 표기법으로 작성한다
    예를 들어 HTML의 onclick은 리액트에서는 onClick으로 작성해야 한다. 또 onkeyup은 onKeyUp으로 작성한다

  • 2) 이벤트에 실행한 자바스크립트 코드를 전달하는 것이 아니라 함수 형태의 값을 전달한다
    HTML에서 이벤트를 설정할 때는 큰 따옴표안에 실행할 코드를 넣었지만 리액트에서는 함수 형태 객체를 전달한다. 앞서 버튼 예제에서도 화살표 함수 문법으로 함수를 만들어 전달. 이렇게 만들어서 전달해도 되고 렌더링 부분 외부에 미리 만들어서 전달해도 된다.

  • 3) DOM 요소에만 이벤트를 설정할 수 있다
    즉 dic, button, input, form, span 등의 DOM 요소에는 이벤트를 설정할 수 있지만 우리가 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없다.

<MyComponent onClick = {doSomething} />

예를 들어, 다음과 같이 Mycomponent에 onClick값을 설정한다면 요것을 클릭할 때 doSomething 함수를 실행하는 것이 아니라 그냥 이름인 onClick인 props를 MyComponent에게 전달해줄 뿐이다.

따라서 컴포넌트에 자체적으로 이벤트를 설정할 수 없다. 하지만 전달받은 props를 컴포넌트 내부의 DOM이벤트로 설정할 수는 있다.

<div onClick = {this.props.onClick}>
	{ ... }
</div>

4.2 예제로 이벤트 핸들링 익히기

4.2.2 onChange 이벤트 핸들링하기

4.2.2.1 onChange 이벤트 설정

EvenPractice 컴포넌트에 input 요소를 렌더링하는 코드와 해당 요소에 onChange 이벤트를 설정하는 코드.

e의 객체는 synthethicEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체. 네이티브 이벤트와 인터페이스가 같으므로 순수 자바스크리브에서 HTML 이벤트를 다룰 때와 똑같이 사용하면 된다.

syntheticEvnet는 네이티브 이벤트와 달리 이벤트가 끝나면 이벤트가 초기화되어서 정보를 참조할 수 없다. 만약 비동기적으로 이벤트 객체를 참조할 일이 있다면 e.persist()함수를 호출해줘야 한다.

값이 바뀔 때마다 바뀌는 값을 콘솔에 기록한다.


4.2.2.2 state에 input 값 담기

state 초기값을 설정하고 이벤트 핸들링 함수 내부에서 this.setState 메서드를 호출해 state를 업데이트!

4.2.2.3 버튼을 누를 때 comment 값을 공백으로 설정



4.2.3 임의 메서드 만들기

이벤트를 처리할 때 렌더링을 하는 동시에 함수를 만들어서 전달해준다. 이 방법 대신 함수를 미리 준비해 전달하는 방법도 있다. 성능상 차이는 거의 없지만 가독성은 훨씬 좋다.

import { Component } from 'react';

이걸 할 때 자동완성 시에 가끔 ./react라고 될 때가 있는데 그럼 다음과 같은 에러가 난다.

Module not found: Error: Can't resolve './react' in ㅇㅇㅇㅇㅇ 

함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어져 버린다. 이로 인해서 임의 메서드가 이벤트로 등록되어도 this를 컴포넌트 자신으로 제대로 가리키기 위해서는 메서드를 this와 바인딩하는 작업이 필요. 만약 바인딩하지 않으면 this가 undefined를 가리키게 된다.

4.2.3.2 Property initializer Syntax 를 사용한 메서드 작성

메서드 바인딩은 생성자 메서드에서 하는 것이 정석. 하지만 이 작업이 불편할 수도. 더 간단하게 하는 방법은 바벨의 transform - class - properties 문법을 사용해 화살표 함수로 메서드를 정의하는 것

훨씬 더 깔끔하다!

4.2.4 input 여러 개 다루기

import가 여러 개일 때 어떻게 작업할까? 메서드를 여러개 만들어야 하나?? 🙋 바로 event 객체를 활용하는 것. e.target.name 값을 사용하면 된다. onChange 이벤트 핸들러에서 e.target.name은 해당 인풋의 name을 가리킨다. 지금은 message. 이런 값을 사용해 state를 설정하면 쉽게 해결할 수 있다.

  • 이렇게 위 메서드를 세팅해 놓고.

  • 밑에 렌더 부분은 이렇게 하면 된다.

위에서 핵심 코드는 요것!

handleChange = (event) => {
    this.setState({
     ⭐ [event.target.name]: event.target.value,⭐
    });
  };

객체 안에서 key를 [ ]로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key 값으로 사용된다.


4.2.5 onKeyPress 이벤트 핸들링


공백이 아니라면 저렇게 된다. state는 초기값이다.


4.3 함수 컴포넌트로 구현해보기

함수형 컴포넌트로 바꿔보자.

위 코드에서는 e.target.name을 활용하지 않고 onChange 함수 두 개를 따로 만들어 주었다. 인풋이 두 개 밖에 없다면 이런 코드도 나쁘지 않다. 그러나 인풋의 개수가 많아지면 e.target.name을 활용하는 것이 더 좋을 수 있다.

아래 코드는 useState를 통해 사용하는 상태에 문자열이 아닌 객체를 넣어 보자.

e.target.name 값을 활용하려면 위와 같이 useState를 쓸 때 인풋 값이 들어 있는 form 객체를 사용해주면 된다.


4.4 정리

리액트에서 이벤트를 다루는 것은 순수 자바스크립트 or 제이쿼리를 사용한 웹 어플리케이션에서 이벤트를 다루는 것과 비슷. 리액트의 장점 중 하나는 자바스크립트에 익숙하다면 쉽게 활용할 수 있다. 기존 HTML DOM event를 알고 있다면 리애그의 컴포넌트 이벤트도 쉽게 다룰 수 있다.

이 장에서 클래스형 컴포넌트도 구현, 함수 컴포넌트로도 구현. 클래스형 컴포넌트로 할 수 있는 대부분의 기능은 함수 컴포넌트로도 구현가능. 함수 컴포넌트에서 여러 개의 인풋 상태를 관리하기 위해 useState에서 form 객체를 사용했는데 이후에 useReducer와 커스텀 Hooks를 사용하면 훨씬 더 편하게 할 수도 있다.


0개의 댓글