본문 바로가기

프론트엔드(Front-End)/React

[REACT] 리액트와 EVENT

리액트의 이벤트(Event)

  • 리액트에서도 여러가지 함수에서 이벤트 객체를 다룰 수 있습니다.
  • Vanila 자바스크립트에서 화살표 함수의 첫번째 매개변수 e는 Event 객체를 의미합니다.
  • 리액트에서도 마찬가지로 화살표 함수의 첫번째 매개변수는 Event객체이나 조금 다릅니다.
  • 리액트에서는 Vanila 자바스크립트를 네이티브 이벤트 객체라고 합니다. 그리고 리액트의 이벤트 객체는 이 네이티브 이벤트 객체를 감싸는 wrapper를 사용하게 됩니다.
  • 이 wrapper 객체를 SyntheticEvent 객체라고 부르며 리액트에서는 이 객체를 통해 이벤트를 핸들링하게 됩니다.
  • 사용 상 네이티브 이벤트 객체와 크게 다르진 않지만, 리액트 이벤트 객체인 만큼 몇 가지 다른점이 존재하긴 합니다.
  • 리엑트에서는 네이티브 이벤트 객체도 물론 사용 가능합니다.
  • 그러나, 리액트에서 별도로 분류하여 다루는 몇 가지 Event 들이 있습니다.
  • 이 이벤트들은 아래의 공식 사이트에서 필요할 때 참고하면 될 것 같습니다.

 

https://reactjs.org/docs/events.html#clipboard-events

 

SyntheticEvent – React

A JavaScript library for building user interfaces

reactjs.org

 

💡 들어가기 전에!

  • 리엑트의 SyntheticEvent 객체는 는 이벤트 종료 후 초기화 되므로 정보를 참조할 수 없습니다.
  • 예컨데 0.5초 뒤에 화살표 함수 안의 e 변수를 비동기로 참조하면 그 안의 값들이 처음과 달라집니다.
  • 만약 비동기적으로 처리하고 싶다면, e.persist() 함수를 호출해주어야 합니다.
  • 컴포넌트 태그에는 이벤트를 설정할 수 없습니다. (본 포스트에서는 <ClassEvent01 /> 등)
  • 그러나 어떤 함수를 변수 형태로 넘겨주어 컴포넌트 내부에서 임의의 메서드를 만들 수는 있습니다.

App.js

import "./App.css";
import "./assets/Custom.css";
import { Fragment } from "react";

// 컴포넌트 삽입
// 클래스형 컴포넌트
import ClassEvent01 from "./components/ClassEvent01";
import ClassEvent02 from "./components/ClassEvent02";
import ClassEvent03 from "./components/ClassEvent03";
import ClassEvent04 from "./components/ClassEvent04";

// 함수형 컴포넌트
import FuncEvent01 from "./components/FuncEvent01";
import FuncEvent02 from "./components/FuncEvent02";

const App = () => {
  const title = "리액트 컴포넌트의 EVENT HANDLING";
  return (
    <>
      <div className="header-div">
        <h1>{title}</h1>
      </div>
      <ClassEvent01 name="value" /> {/* 이렇게 작성하면 props 속성명이 name인 데이터로 넘거 가게 됨 */}
      <ClassEvent02 />
      <ClassEvent03 />
      <ClassEvent04 />
      <FuncEvent01 />
      <FuncEvent02 />
    </>
  );
};

export default App;

콘솔창에서 SyntheticEvent 확인하기

 

 

클래스 컴포넌트로 이벤트 핸들러 만들기1 (ClassEvent01.js)

import { Component } from "react";
import { Fragment } from "react";

class ClassEvent01 extends Component {
  state = {
    text: "",
  };
  render() {
    const { text } = this.state;
    return (
      <>
        <div className="class-comp">
          <div className="text-box">
            <h1>이벤트 연습1</h1>
            <p>{text}</p>
            <input
              type="text"
              name="message"
              placeholder="아무 글자나 입력해 보세요"
              onChange={(e) => {
                console.dir(e);
                this.setState({ text: e.target.value });
              }}
            />
          </div>
          <button
            onClick={(e) => {
              alert(text);
              this.setState({ text: "" });
            }}
          >
            확인
          </button>
        </div>
      </>
    );
  }
}

export default ClassEvent01;

 

클래스 컴포넌트로 이벤트 핸들러 만들기2 (ClassEvent02.js)

import { Component } from "react";
import { Fragment } from "react";

class ClassEvent02 extends Component {
  state = {
    text: "",
  };
  // 이곳에 메서드를 작성
  handleChange = (e) => {
    this.setState({
      text: e.target.value,
    });
  };

  handleClick = () => {
    alert(this.state.text);
    this.setState({ text: "" });
  };

  render() {
    const { text } = this.state;
    return (
      <>
        <div className="class-comp">
          <div className="text-box">
            <h1>이벤트 연습2</h1>
            <p>{text}</p>
            <input
              type="text"
              name="message"
              placeholder="아무 글자나 입력해 보세요"
              value={text}
              onChange={this.handleChange}
            />
          </div>
          <button onClick={this.handleClick}>확인</button>
        </div>
      </>
    );
  }
}

export default ClassEvent02;

 

 

 

클래스 컴포넌트로 이벤트 핸들러 만들기3 (ClassEvent03.js)

import { Component } from "react";
import { Fragment } from "react";

class ClassEvent03 extends Component {
  state = {
    username: "",
    text: "",
  };
  // 이곳에 메서드를 작성
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  };

  handleClick = () => {
    alert(this.state.username + " : " + this.state.text);
    this.setState({
      text: "",
      username: "",
    });
  };

  render() {
    const { text, username } = this.state;
    return (
      <>
        <div className="class-comp">
          <div className="text-box">
            <h1>이벤트 연습3</h1>
            <p>{username}</p>
            <p>{text}</p>
            <input
              type="text"
              name="username"
              placeholder="아무 이름이나 입력해 보세요"
              value={username}
              onChange={this.handleChange}
            />
            <br />
            <input
              type="text"
              name="text"
              placeholder="아무 글자나 입력해 보세요"
              value={text}
              onChange={this.handleChange}
            />
          </div>
          <button onClick={this.handleClick}>확인</button>
        </div>
      </>
    );
  }
}

export default ClassEvent03;
  • 자바스크립트 객체의 프로퍼티 명(key 값)을 []로 감싸면 실제로 프로퍼티가 가지고 있는 값으로 바뀐다.
  • e.target.name =”hello”면 name : hello이런 식으로 바뀐다는 뜻 이다.

 

 

클래스 컴포넌트로 이벤트 핸들러 만들기4 (ClassEvent04.js)

  • 엔터 치면 정보가 뜨게 설정
import { Component } from "react";
import { Fragment } from "react";

class ClassEvent04 extends Component {
  state = {
    username: "",
    text: "",
  };
  // 이곳에 메서드를 작성
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  };

  handleClick = () => {
    alert(this.state.username + " : " + this.state.text);
    this.setState({
      text: "",
      username: "",
    });
  };

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

  render() {
    const { text, username } = this.state;
    return (
      <>
        <div className="class-comp">
          <div className="text-box">
            <h1>이벤트 연습4</h1>
            <p>{username}</p>
            <p>{text}</p>
            <input
              type="text"
              name="username"
              placeholder="아무 이름이나 입력해 보세요"
              value={username}
              onChange={this.handleChange}
              onKeyDown={this.handleKeyPress}
            />
            <br />
            <input
              type="text"
              name="text"
              placeholder="아무 글자나 입력해 보세요"
              value={text}
              onChange={this.handleChange}
              onKeyDown={this.handleKeyPress}
            />
          </div>
          <button onClick={this.handleClick}>확인</button>
        </div>
      </>
    );
  }
}

export default ClassEvent04;

 

 


 

함수형 컴포넌트 이벤트 핸들러 만들기 1 (FuncEvent01.js)

import { useState, Fragment } from "react";

const FuncEvent01 = () => {
  const [username, setUsername] = useState("");
  const [text, setText] = useState("");
  // 함수형 컴포넌트의 이벤트 핸들링 메서드
  // 일단 가장 쉬운 방법은 이벤트에 맞게 메서드를 별도로 선언하는 것이다.
  // 하지만 이런 식의 코드 스타일은 프로젝트가 커지면 하드코딩으로 변하기 딱 좋다...
  const onChangeUsername = (e) => setUsername(e.target.value);
  const onChangeText = (e) => setText(e.target.value);
  const onClick = () => {
    alert(username + " : " + text);
    setUsername("");
    setText("");
  };
  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      onClick();
    }
  };

  return (
    <>
      <div className="class-comp">
        <div className="text-box">
          <h1>함수형 이벤트 연습1</h1>
          <p>{username}</p>
          <p>{text}</p>
          <input
            type="text"
            name="username"
            placeholder="아무 이름이나 입력해 보세요"
            value={username}
            onChange={onChangeUsername}
            onKeyDown={handleKeyDown}
          />
          <input
            type="text"
            name="text"
            placeholder="아무 글자나 입력해 보세요"
            value={text}
            onChange={onChangeText}
            onKeyDown={handleKeyDown}
          />
        </div>
        <button onClick={onClick}>확인</button>
      </div>
    </>
  );
};

export default FuncEvent01;
  • 함수형은 클래스형과 달리 확실히 state, 변수, 메서드 선언이 조금 까다롭다.
  • 함수형 컴포넌트에서는 위와 같이 dom 별로 이벤트 핸들러를 작성할 수도 있고,
  • 이것은 곧 프로젝트의 규모가 커지면 하드 코딩하게 되는 원인이 된다.

 

 

 

함수형 컴포넌트 이벤트 핸들러 만들기 2 (FuncEvent02.js)

import { useState, Fragment } from "react";

const FuncEvent02 = () => {
  const [form, setForm] = useState({
    text: "",
    username: "",
  });
  const { text, username } = form;
  const handleChange = (e) => {
    const nextForm = {
      ...form, // 기존의 form 내용을 복사하고
      [e.target.name]: e.target.value, // 원하는 값 덮어쓰기
    };
    setForm(nextForm);
  };

  const onClick = () => {
    alert(username + " : " + text);
    this.setForm({
      text: "",
      username: "",
    });
  };
  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      onClick();
    }
  };

  return (
    <>
      <div className="class-comp">
        <div className="text-box">
          <h1>함수형 이벤트 연습2</h1>
          <p>{username}</p>
          <p>{text}</p>
          <input
            type="text"
            name="username"
            placeholder="아무 이름이나 입력해 보세요"
            value={username}
            onChange={handleChange}
            onKeyDown={handleKeyDown}
          />
          <input
            type="text"
            name="text"
            placeholder="아무 글자나 입력해 보세요"
            value={text}
            onChange={handleChange}
            onKeyDown={handleKeyDown}
          />
        </div>
        <button onClick={onClick}>확인</button>
      </div>
    </>
  );
};

export default FuncEvent02;
  • 함수형 컴포넌트에서도 destructuring assignment 를 사용하면 소프트 코딩이 가능하다.