React 뿌시기 4일차 - Feat. 리액트를 다루는 기술

SOLEE_DEV·2021년 8월 18일
0

React.js

목록 보기
8/8

이벤트 핸들링

사용자가 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트라고 함
예를 들어 버튼에 마우스 커서를 올렸을 때는 onmouseover 이벤트를 실행하고, 클릭했을 때는 onclick 이벤트를 실행, Form 요소는 값이 바뀔 때 onchange 이벤트를 실행

리액트의 이벤트 시스템

사용법은 일반 HTML에서 이벤트를 작성하는 것과 비슷함

리액트에서 이벤트를 사용할 때 주의 사항

  1. 이벤트 이름은 카멜 표기법으로 작성
  2. 이벤트에 실행할 JS코드를 전달하는 것이 아닌, 함수 형태의 값을 전달
  3. DOM 요소에만 이벤트를 설정할 수 있음 (직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없음)

이벤트 종류

  • Clipboard
  • Composition
  • Keyboard
  • Focus
  • Form
  • Mouse
  • Selection
  • Touch
  • UI
  • Wheel
  • Media
  • Image
  • Animation
  • Transition




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

이벤트 핸들링 실습 단계

  1. 컴포넌트 생성 및 불러오기
  2. onChange 이벤트 핸들링하기
  3. 임의 메소드 만들기
  4. input 여러 개 다루기
  5. onKeyPress 이벤트 핸들링하기

1. 컴포넌트 생성 & 이벤트 핸들링

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) => {
                        this.setState({
                            message: e.target.value
                        })
                    }}
                />

                <button
                    onClick={() => {
                        alert(this.state.message);
                        this.setState({
                            message: ''
                        })
                    }}
                >
                    확인
                </button>

                <h3>{this.state.message}</h3>
            </div>
        );
    }
}

export default EventPractice;

e 객체

  • SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체
  • 네이티브 이벤트와 인터페이스가 같으므로 순수 JS에서 이벤트를 다룰 때와 동일하게 사용하면 O
  • 네이티브 이벤트와 달리 이벤트가 끝나고 나면 이벤트가 초기화되므로 정보를 참조할 수 없음
    => 0.5초 뒤에 e 객체를 참조하면 e 객체 내부의 모든 값이 비워지게 됨!
  • 따라서, 만약 비동기적으로 이벤트 객체를 참조할 일이 있다면 e.persist() 함수를 호출해 주어야 함

2. 임의 메서드 만들기

  • 이벤트를 처리할 때 렌더링을 하는 동시에 함수를 만들어서 전달해 주는 방법 대신 함수를 미리 준비하여 전달하는 방법도 있음
  • 성능상으로는 차이가 거의 없지만, 가독성을 훨씬 높다!

기본 코드

onChange, onClick에 전달한 함수를 따로 빼내서 컴포넌트 임의 메서드로 생성

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>

                <h3>{this.state.message}</h3>
            </div>
        );
    }
}

export default EventPractice;
  • 함수가 호출될 때 this는 호출부에 따라 결정
  • 클래스의 임의 메소드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메소드와 this에 관계가 끊어져 버림
  • 이 때문에 임의 메소드가 이벤트로 등록되어도 this를 컴포넌트 자신으로 제대로 가리키기 위해서는 메소드는 this와 바인딩하는 작업이 필요
  • 만약 바인딩하지 않은 경우라면 this가 undefined를 가리키게 됨
  • 현재 constructor 함수에서 함수를 바인딩하는 작업이 이루어지고 있음

Property Initializer Syntax를 사용한 메서드 작성

바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메소드를 정의하면 this 바인딩을 해주지 않아도 됨!

import React, {Component} from 'react';

class EventPractice extends Component {
    state = {
        message: ''
    }

    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>

                <h3>{this.state.message}</h3>
            </div>
        );
    }
}

export default EventPractice;

3. input 여러 개 다루기

e.target.name 값을 사용하면 해당 인풋의 name을 구분해서 state를 변경하면 됨

this.setState({
  [e.target.name] : e.target.value
  // 이런식으로!
})

객체 안에서 key를 [] 로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key값으로 사용됨

4. onKeyPress 이벤트 핸들링

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

onKeyPress={this.handleKeyPress}




함수형 컴포넌트로 구현해 보기

import React, {useState} from 'react';

const EventPractice = () => {
    const [form, setForm] = useState({
        username: '',
        message: ''
    });

    const { username, message } = form;

    const onChange = e => {
        console.log(e.target.value);
        const nextForm = {
            ...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;




정리

  • 리액트에서 이벤트를 다루는 것은 순수 JS, JQuery를 사용한 웹 App에서 이벤트를 다루는 것과 비슷함
  • 리액트의 장점 중 하나는 js에 익숙하다면 쉽게 활용할 수 있다는 것
  • 따라서 기존 HTML DOM Event를 알고있다면 리액트의 컴포넌트 이벤트도 쉽게 다룰 수 있음
profile
Front-End Developer

0개의 댓글