상세 컨텐츠

본문 제목

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

21-22/21-22 리액트 마스터

by 도리에몽 2021. 10. 11. 14:00

본문

728x90

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

이벤트 : 사용자가 웹브라우저에서 DOM 요소들과 상호작용하는 것

리액트의 이벤트 작성법은 일반 HTML에서의 이벤트 작성법과 비슷합니다.

 

※주의 사항

  ① 이벤트 이름은 카멜 표기법으로 작성

  ② 이벤트 설정 시 함수 형태의 객체 전달

       - 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니다.

  ③  DOM 요소에만 이벤트 설정 가능

       - 직접 만든 컴포넌트에는 이벤트 자체 설정 불가

         그냥 이름이 onClick인 props를 컴포넌트에게 전달할 뿐

           ⇨ 전달받은 props를 컴포넌트 내부의 DOM이벤트로 설정은 가능하다. 

 

▶이벤트 종류

더보기
더보기

Clipboard, Composition, Keyboard, Focus, Form, Mouse, Selection,

Touch, UI, Wheel, Media, Image, Animation, Transition

더 많은 이벤트 종류 : https://facebook.github.io/react/docs/events.html


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

1. 컴포넌트 생성 및 불러오기

//EventPractice.js
import React, {Component} from 'react';

class EventPractice extends Component{
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
      </div>
    );
  }
}

export default EventPractice;
//App.js
import React from 'react';
import EventPractice from './EventPractice';

const App = () => {
  return <EventPractice />;
};

export default App;

2. onChange 이벤트 핸들링하기

//EventPractice.js
import React, {Component} from 'react';

class EventPractice extends Component{
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="아무거나 입력해 보세요"
          onChange={
            (e) => {
              console.log(e);
            }
          }
        />
      </div>
    );
  }
}

export default EventPractice;

   e 객체 : SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체

        - 이벤트가 끝나고 나면 초기화되므로 참조 불가

           ⇨ 비동기적으로 이벤트 객체를 참조하려면 e.persist() 함수 호출

4.2.2.2 예제, 4.2.2.3 예제

3. 임의 메서드 만들기

지금까지는 이벤트를 처리할 때 렌더링을 하는 동시에 함수를 만들어서 전달해 주었습니다.

이 방법 대신 함수를 미리 준비하여 전달하는 방법을 사용하면 가독성이 높아집니다.

 

앞에서 실습한 onChange와 onClick에 전달한 함수를 빼내서 컴포넌트 임의 메서드로 만들어 봅시다

<기본 방식>
//EventPractice.js
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(e) {
    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;

임의 메서드가 특정 HTML요소의 이벤트로 등록되는 과정 중 메서드와 this의 관계가 끊어진다.
  ⇨ 메서드를 this와 바인딩하는 작업이 필요하다

      위의 코드에서는 constructor 함수에서 바인딩 작업이 이루어지고 있음
<Property Initializer Syntax 사용한 방식>
메서드 바인딩 작업이 불편하다고 느껴져 이 작업을 더 간단하게 하고 싶다면
  ⇨ 바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메서드를 정의하기
//EventPractice.js
import React, {Component} from 'react';

class EventPractice extends Component {
  state = { message: '' }
  
  handleChange = (e) => {
    this.setState({ message: e.target.value });
  }
  
  handleClick = () => {
    alert(this.state.message);
    this.setState({ message: '' });
  }
  
  render() {
  //기본 방식에서 사용한 코드와 동일한 코드 작성
}
export default EventPractice;​

4. input 여러 개 다루기

  -> input이 여러 개일 때는 e.target.name처럼 event객체를 활용하면 됩니다.

//EventPractice.js
import React, {Component} from 'react';

class EventPractice extends Component{
  state = { username:'', message:'' }
  
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }
  
  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;

 

 

⇒객체 안에서 key를 [ ]로 감싸면

그 안에 넣은 레퍼런스가 가리키는 실제 값이 key값이 된다.

 

 

5. onKeyPress 이벤트 핸들링하기

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

3. 함수형 컴포넌트로 구현

위의 코드들은 모두 클래스형 컴포넌트로 구현되어 있으나, 함수형 컴포넌트로도 똑같이 구현할 수 있습니다.

//EventPractice.js
import React, {useState} from 'react';

const EventPractice = () => {
  const [username, setUsername] = useState('');
  const [message, setMessage] = useState('');
  const onChangeUsername = e => setUsername(e.target.value);
  const onChangeMessage = e => setMessage(e.target.value);
  const onClick = () => {
    alert(username + ': '+message);
    setUsername('');
    setMessage('');
  }
  const onKeyPress = e => {
    if(e.key === 'Enter') {
      onClick();
    }
  };
  return (
      <div>
        <h1>이벤트 연습</h1>
        <input 
          type="text"
          name="username"
          placeholder="사용자명"
          value={username}
          onChange={onChangeUsername}
        />
        <input
          type="text"
          name="message"
          placeholder="아무거나 입력해보세요"
          value={message}
          onChange={onChangeMessage}
          onKeyPress={onKeyPress}
        />
        <button onClick={onClick}>확인</button>
      </div>
    };
  }
}
export default EventPractice;

위의 코드에서는 onChange 관련 함수를 따로 만들어주었는데, 인풋의 개수가 많아질 경우 e.target.name을 활용하는 것이 더 좋을 수도 있습니다. 

아래는 useState를 통해 상태에 문자열이 아닌 객체를 넣도록 수정한 코드입니다.

//EventPractice.js
import React, {useState} from 'react';

const EventPractice = () => {
  const [form, setForm] = useState({ username:'', message:''});
  const [username, setUsername] = form;
  const onchange = e => {
    const nextForm = {
      ...form,
      [e.target.name]: e.target.value
    };
    setForm(nextForm);
  };
  
  const onClick = () => {
    alert(username + ': '+message);
    setUsername('');
    setMessage('');
  }
  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;

useState를 쓸 때는 인풋 값들이 들어 있는 form 객체를 사용해주면 됩니다.

  ⇒ 8장의 useReducer와 커스텀 Hooks를 사용하면 작업이 더 편리합니다.


<4장 Quiz>

Q1) 리액트에서 이벤트를 설정할 때 자바스크립트 코드를 전달한다.

답 : (O, X)

 

Q2) (     )에만 이벤트 설정이 가능하고, 직접 만든 컴포넌트에는 이벤트 설정이 불가능하다.

 

Q3) e 객체는 이벤트가 끝나고 나면 초기화되므로 참조 불가하다.

답 : (O, X)

 

Q4) 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어지는 것을 방지하기 위해 메서드와 this(     )하는 작업이 필요하다.

 

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

 

<정답 확인>

더보기
더보기

A1) X

A2) DOM 요소

A3) O

A4) 바인딩

A5) key값

728x90

관련글 더보기