본문 바로가기
Web/React

[React] 4-1 이벤트

by 개발자 아구몬 2023. 12. 2.

이벤트


사용자가 웹 브라우저에서 DOM 요소와 상호작용하는 것을 이벤트(event) 라고 한다. React는 JS를 기반으로 하고 있기 때문에 이벤트 역시 JS의 그것과 크게 다르지 않다.

함수형 컴포넌트

import React, { useState } from "react";

const Counter = () => {
  const [number, setNumber] = useState(0);
  const onClickNumber = () => setNumber(number + 1);

  return (
    <div>
      <button onClick={onClickNumber}>+1</button>
    </div>
  );
};

export default Counter;

 

이전에도 우리는 button 엘리먼트의 onClick 속성을 이용하여, 버튼 클릭 시 이벤트가 발생하게 코드를 짠 적 있다. 이전에는 onClick 속성에 익명 화살표 함수를 바로 대입하였다면, 위처럼 이벤트 함수를 따로 정의한 뒤에 대입해도 된다.

이벤트 함수명은 camelCase를 사용하며, 위처럼 간단히 state를 변경하는 경우엔 on+이벤트명+state 명 과 같은 형식을 사용하지만 복잡한 로직이 있는 경우 handle+작업명 을 사용하는 것이 개발자 사이의 관례이다.

 

...
<MyComponent onClick={onClickNumber}> ... </MyComponent>
...

 

이벤트 설정은 DOM 요소에만 가능하며, 컴포넌트에는 직접적으로 설정이 불가능하다. 위와 같이 두면 단지 onClick 이라는 이름의 props가 설정될 뿐이다.

 

클래스형 컴포넌트

import React, { Component } from "react";

class Counter extends Component{
  state = {
    number:0
  }

  constructor(props){
    super(props);
    this.onClickNumber = this.onClickNumber.bind(this);
  }

  onClickNumber(e){
    this.setState({
      number: this.state.number + 1;
    })
  }

  render(){
    return (
	    <div>
	      <button onClick={this.onClickNumber}>+1</button>
	    </div>
    );
  }
}

export default Counter;

 

함수가 호출될 때 this는 호출부에 따라 결정된다. 클래스의 메서드가 특정 HTML요소의 이벤트로 등록되면 일반 함수처럼 등록되고, 이 때 해당 클래스의 인스턴스를 가리키는 this의 관계가 끊어져버린다. 따라서 클래스형 컴포넌트에서 이벤트를 처리할 클래스 메서드를 선언할 때에는, bind()함수를 이용하여 constructor에서 this가 계속 컴포넌트 인스턴스를 가리키도록 바인딩해야한다.

 

onClickNumber = (e) => {
    this.setState({
      number: this.state.number + 1;
    })
  }

 

바벨의 transform-class-properties 문법을 사용하면 constructor와 bind없이 간단하게 구현 가능하다. 이 문법을 사용하면 화살표함수 선언시점의 this를 캡처하여 사용하므로, 별도의 bind 없이도 안전하게 this를 사용할 수 있다.

 

event객체


import React, { useState } from "react";

const Counter = () => {
  const [text, setText] = useState("");

  return (
    <div>
      <div> {text} </div>
      <input
        type="text"
        name="message"
        placeholder="아무거나 입력해보세요"
        onChange={(e) => {
          setText(e.target.value);
        }}
      />
    </div>
  );
};

export default Counter;

 

일반적으로 event를 사용할 때, 화살표 함수의 첫번째 매개변수는 SyntheticEvent웹 브라우저의 네이티브 이벤트를 감싸는 wrapper 객체이다. 이름은 크게 상관 없지만, 관례적으로 e 혹은 event 를 사용한다.

e의 target 프로퍼티는 이벤트가 발생한 DOM 요소를 나타내며, 그 요소의 value 프로퍼티는 입력필드의 을 의미한다. e.target.value는 굉장히 많이 사용하는 값이므로 암기해두도록 하자.

 

💡 React 이벤트의 참조
네이티브 이벤트와 달리 이벤트가 끝나면 초기화 되어 정보를 참고할 수 없으므로, 이후에 비동기적으로 참조하기 위해선 e.persist()함수를 호출해야 한다.
const handleChange = (e) => {
  e.persist(); // e 객체 유지
  setTimeout(() => {
    console.log(e.target.value); // 비동기적으로 e 객체 사용
  }, 1000);
};

 

input이 여러개인경우

import React, { useState } from "react";

const Counter = () => {
  const [messages, setMessages] = useState({
    message: "",
    message2: "",
  });

  const { message, message2 } = messages;

  const handleChange = (e) => {
    setMessages({
      ...messages,
      [e.target.name]: e.target.value,
    });
  };

  return (
    <div>
      <input
        type="text"
        name="message"
        placeholder="아무거나 입력해보세요"
        value={message}
        onChange={handleChange}
      />
      <input
        type="text"
        name="message2"
        placeholder="아무거나 입력해보세요"
        value={message2}
        onChange={handleChange}
      />
    </div>
  );
};

export default Counter;

 

input 등 값이 변화하는 것을 감지하기 위해서는 onChange 속성을 사용한다.

JS 객체 안에서 key를 []로 감싸면 내부 레퍼런스가 가리키는 실제값이 key값으로 사용된다. e.target.name은 해당 DOM의 이름을 나타내는 프로퍼티로, 위와 같이 state의 key값을 각 DOM의 name 필드에 배분하여 사용할 수 있다.

 

키를 누를경우

handleKeyPress = (e) => {
	if(e.key === 'Enter'){
		this.handleClick();
	}
}

키를 누를경우에는 onKeyPress 속성을 사용할 수 있으며, 이벤트 객체에선 e.key 프로퍼티를 사용할 수 있다.

'Web > React' 카테고리의 다른 글

[React] 3-3. 컴포넌트 반복  (1) 2023.12.04
[React] 5-1. ref  (1) 2023.12.04
[React] 3-2. state  (1) 2023.11.29
[React] 3-1. 컴포넌트와 props  (0) 2023.11.27
[React] 2-2. JSX  (2) 2023.11.27