[React] 이벤트 핸들링

강은비·2022년 1월 11일
0

React

목록 보기
7/36
post-custom-banner

react 스터디에서 리액트를 다루는 기술이라는 책을 선정했고 이 책을 읽고 배운 것을 바탕으로 작성되었다.


Event: 사용자가 웹 브라우제에서 DOM 요소들과 상호작용하는 것

❗ React에서 이벤트 사용할 때 주의사항

  1. 이벤트 이름은 카멜표기법으로 작성해야 한다.
  2. 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달한다.
  3. DOM 요소에만 이벤트를 설정할 수 있다.
    • 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없다.
    • <MyComponent onClick={doSomething}/> : props로 메서드 전달

❗ 이벤트 종류

  • Clipboard 이벤트
  • Composition 이벤트
  • Keyboard 이벤트
  • Focus 이벤트
  • Form 이벤트
  • Generic 이벤트
  • Mouse 이벤트
  • Pointer 이벤트
  • Selection 이벤트
  • Touch 이벤트
  • UI 이벤트
  • Wheel 이벤트
  • Media 이벤트
  • Image 이벤트
  • Animation 이벤트
  • Transition 이벤트

참고: [React] 이벤트 종류


📙 SyntheticEvent

  • 이벤트 핸들러는 모든 브라우저에서 이벤트를 동일하게 처리하기 위한 이벤트 래퍼 SyntheticEvent 객체를 전달받습니다.
  • 인터페이스는 브라우저의 고유 이벤트와 같지만 모든 브라우저에서 동일하게 동작합니다.
  • 모든 SyntheticEvent 객체 다음과 같은 속성을 가진다.
boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent   // 브라우저 고유 이벤트
void preventDefault()
boolean isDefaultPrevented()
void stopPropagation()
boolean isPropagationStopped()
void persist()
DOMEventTarget target
number timeStamp
string type
  • SyntheticEvent 객체 는 풀링된다. 성능상의 이유로 SyntheticEvent 객체는 재사용되고 모든 속성은 이벤트 핸들러가 호출되고 난 다음 초기화된다. 따라서 비동기적으로 이벤트 객체에 접근할 수 없다.
  • 이벤트가 발생할 때마다 이벤트 객체를 만들면 Garbage Collection이 자주 발생하기 때문에 React는 Object Pool 방식을 사용한다.
  • 이벤트가 발생할 때마다 풀로부터 하나의 인스턴스를 가져오고 프로퍼티 값을 채운다. 통합 이벤트 인스턴스는 이벤트 핸들러의 동작이 끝날 때 해제돼 다시 풀로 돌아간다.
function handleChange(e) {
  // This won't work
  setTimeout(() => {
    console.log(e.target.value); // Too late!
  }, 100);
}
  • 비동기적으로 이벤트 객체를 참조할 일이 있다면, e.persist()를 호출해야 한다.
function handleChange(e) {
  // Prevents React from resetting its properties:
  e.persist();

  setTimeout(() => {
    console.log(e.target.value); // Works
  }, 100);
}
  • v17부터 SyntheticEvent가 더 이상 풀링되지 않기 때문에 e.persist()는 아무런 동작을 하지 않는다.

📙 예시

import { useState } from "react";

function EventPractice() {
    const [inputs, setInputs] = useState({
        username: "",
        message: ""
    });
    // 비구조화 할당을 통해 값 추출
    const { username, message } = inputs;
    const handleChange = (e) => {
        const { name, value } = e.target;
        setInputs({
            ...inputs,   	// 기존의 inpus 객체 복사한 뒤
            [name]: value   // 객체 키 동적으로 정의하기 (name 키를 가진 값을 value로 설정, 덮어쓰기)
        });
    };
    
    const handleClick = () => {
        alert(`${username}: ${message}`);
        setInputs({
            username: "",
            message: ""
        });
    }
    
    const handleKeyPress = (e) => {
        if (e.key === "Enter"){
            handleClick();
        }
    }
    
    return (
       <div>
           <input 
               type="text"
               name="username"
               value={username}
               onChange={handleChange}/>
           <input 
               type="text"
               name="message"
               value={message}
               onChange={handleChange}
               onKeyPress={handleKeyPress}/>
           <button >확인</button>
       </div>
    );
};

export default EventPractice;
post-custom-banner

0개의 댓글