본문 바로가기
Frontend/ReactJS(완)

React - 4장 : 이벤트 핸들링

by 리키이 2023. 2. 8.

4-1. 리액트의 이벤트 시스템

1) 이벤트를 사용할 때 주의 사항

- 이벤트 이름은 카멜 표기법으로 작성한다.

  - ex) onclick(x) -> onClick

- 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달한다.

- DOM 요소에만 이벤트를 설정할 수 있다.

  - 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없다.

 

4-2. 예제로 이벤트 핸들링 익히기

1) onChange 이벤트

- onChange 이벤트는  Form 요소에 값이 변하면 발생하는 이벤트이다.

- onChange 함수안에 e 객체는 SyntheticEvent, 웹 브라우저의 네이티브 이벤트를 감싸는 객체이다.

- 이벤트가 끝나고 나면 초기화되므로 정보를 참조할 수 없다.

- 만약 비동기적으로 이벤트 객체에 참조할 일이 생긴다면 밑에 코드를 보면 알 수 있다.

   - onChange 함수 안에 setTimeout 함수를 적용 시키려면 e.persist() 함수를 호출해주면 정상적으로 작동이 된다.

   - e.persist() 함수를 넣어주는 이유는 기존에 사용하고 있던 이벤트 풀 ( Event Pool ) 에서 제거되고 사용자 코드로

      사용이 되기 때문!!

 

import React, { Component } from 'react';
 
class EventPractice extends Component {
 
  state = {
    message: ''
  }
 
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="아무거나 입력해 보세요"
          value={this.state.message}
          onChange={(e) => {
                e.persist();
                console.log(e.type);
                console.log(e.target.value);
                setTimeout(() => {
                    console.warn(e.type);
                });
            }
        />
      </div>
    );
  }
}
 
export default EventPractice;

 

2) 임의 메서드 만들기

- 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달한다.

  - 성능상으로는 차이가 거의 없지만, 가독성은 훨씬 높다.

- 밑에 코드를 보면 constructor안에 bind(this)가 되있는데 임의 메서드가 이벤트로 등록되어도 this가 컴포넌트

  자신으로 제대로 가르키기 위해서는 메서드를 this와 바인딩하는 작업이 필요하다.

  - 바인딩하지 않는 경우라면 this가 undefined를 가리키게 된다.

 

import React, { Component } from 'react';
 
class EventPractice extends Component {
 
  state = {
    message: ''
  }
 
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
 
  handleChange(e) {
    this.setState({
      message: e.target.value
    });
  }
 
  handleClick() {
    alert(this.state.message);
    this.setState({
      message: ''
    });
  }
 
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="아무거나 입력해 보세요"
          value={this.state.message}
          onChange={this.handleChange}
        />
        <button onClick={this.handleClick}>확인</button>
      </div>
    );
  }
}
 
export default EventPractice;

 

3) Property Intializer Syntax 를 사용한 메서드 작성

- 메서드 바인딩은 생성자 메서드에서 하는 것이 정석이다. 그렇다보니 새 매서드를 만들 때마다 constructor도

  수정해야 하는게 불편할 수 있다.

- 이것을 간단하게 하는 방법도 있는데 바벨의 transform-class-properties 문법을 사용하여 화살표 함수형태로

  메서드를 정의 할 수 있다.

- 화살표 함수를 통해서 thisReact 구성 요소 내에서 정의한 모든 메서드에 컨텍스트를 종속적으로 바인딩할 필요가

  없어진다.

- 코드가 훨씬 간결하고 깔끔해진다.

 

<생성자 메서드를 사용한 형태>
constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
 
  handleChange(e) {
    this.setState({
      message: e.target.value
    });
  }
 
  handleClick() {
    alert(this.state.message);
    this.setState({
      message: ''
    });
  }
  
  
  
<화살표 함수 형태> 
  handleChange = (e) => {
    this.setState({
      message: e.target.value
    });
  }
 
  handleClick = () => {
    alert(this.state.message);
    this.setState({
      message: ''
    });
  }

 

4) input 여러 개 다루기

- input이 여러 개일 때 메서드를 여러 개 만드는 것도 방법이지만 더 쉽게 처리하기 위해서는 event 객체

 활용하는 것이다.

- e.target.name 값을 활용하면 된다.

- e.target.name에 각각 input에서 설정한 name 값이 들어가게 되고

- e.target.value는 각각 input에서 입력한 input value값이 들어가게 된다

 

import React, { Component } from 'react';
 
class EventPractice extends Component {
 
  state = {
    username: '',
    message: ''
  }
 
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }
 
  handleClick = () => {
    alert(this.state.username + ': ' + this.state.message);
    this.setState({
      username: '',
      message: ''
    });
  }
 
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input 
          type="text"
          name="username"
          placeholder="사용자명"
          value={this.state.username}
          onChange={this.handleChange}
        />
        <input 
          type="text"
          name="message"
          placeholder="아무거나 입력해 보세요"
          value={this.state.message}
          onChange={this.handleChange}
        />
        <button onClick={this.handleClick}>확인</button>
      </div>
    );
  }
}
 
export default EventPractice;

 

- [e.target.name] 을 작성한 이유는 객체 안에서 key를 []로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이

  key로 사용된다.

//위에 내용을 추가로 덧붙이자면 다음과 같은 객체가 있을때
const name = "홍길동";
const object = {
 [name] : 'value'
}

// 결과는 다음과 같다.
{
 '홍길동' : 'value'
}

 

4-3. 함수 컴포넌트로 구현해 보기

- 아래의 코드에서 const { username, message } = form; 이것을 넣은 이유는 form.username , form.message를

  넣을 수 있지만 편하게 사용하기 위해서 비구조화 할당을 해준 것이다.

 

import React, { useState } from 'react';
 
const EventPractice = () => {
  const [form, setForm] = useState({
    username: '',
    message: ''
  });
  const { username, message } = form;
  //바로 위의 코드의 의미는 다음과 같다.
  // const form: {
  //     username: string;
  //     message: string;
  // }
  
  
  //불변성 유지를 위해
  const onChange = e => {
    const nextForm = {
      ...form, // 기존의 form 내용을 이 자리에 복사한 뒤
      [e.target.name]: e.target.value // 원하는 값을 덮어 씌우기
    };
    setForm(nextForm);
  };
  const onClick = () => {
    alert(username + ': ' + message);
    setForm({
      username: '',
      message: ''
    });
  };
  const onKeyPress = e => {
    if (e.key === 'Enter') {
      onClick();
    }
  };
  return (
    <div>
      <h1>이벤트 연습</h1>
      <input
        type="text"
        name="username"
        placeholder="사용자명"
        value={username}
        onChange={onChange}
      />
      <input
        type="text"
        name="message"
        placeholder="아무거나 입력해 보세요"
        value={message}
        onChange={onChange}
        onKeyPress={onKeyPress}
      />
      <button onClick={onClick}>확인</button>
    </div>
  );
};
export default EventPractice;

 

'Frontend > ReactJS(완)' 카테고리의 다른 글

React - 6장 : 컴포넌트 반복  (0) 2023.02.13
React - 5장 : ref. DOM에 이름 달기  (0) 2023.02.09
React - 3장 : 컴포넌트  (0) 2023.02.06
React - 2장 : JSX  (0) 2023.02.02
React - 1장 : React 이해  (0) 2023.02.01

댓글