본문 바로가기

react

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

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

 

- 사용자가 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트(event)라고 함 

 

- 이벤트를 사용할 떄 주의사항

 

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

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

3) DOM 요소에만 이벤트를 설정할 수 있음

 

 

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

 

1) onChange 이벤트 핸들링 하기 

 

onChange 이벤트 설정

 

EventPractice.js

import { Component } from "react";

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

export default EventPractice;

- 비동기적으로 이벤트 객체를 참조할 일이 있다면 e.persist() 함수를 호출해줘야 함 

- onChange 이벤트가 발생할 때, 앞으로 변할 인풋값인 e.target.value를 콘솔에 기록 

 

 

state에 input 값 담기 

 

- 생성자 메서드인 constructor에서 state 초깃값을 설정하고, 이벤트 핸들링 함수 내부에서 this.setState 메서드를 호출하여 state를 업데이트 

 

EventPractice.js

import { 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
                            })
   
                        }
                    }
                />
            </div>
        )
    }
}

export default EventPractice;

 

버튼을 누를 때 comment 값을 공백으로 설정 

 

- input 요소 코드 아래쪽에 button을 하나 만들고, 클릭 이벤트가 발생하면 현재 comment 값을 메시지 박스로 띄운 후 comment 값을 공백으로 설정 

 

EventPractice.js

 

import { 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>
            </div>
        )
    }
}

export default EventPractice;

 

 

 

 

2) 임의 메서드 만들기

 

- onChange와 onClick에 전달한 함수를 따로 빼내서 컴포넌트 임의 메서드 만들기 

 

기본방식 

 

- 함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어져 버림 

 -> 임의 메서드가 이벤트로 등록되어도 this가 컴포넌트 자신으로 제대로 가리키기 위해서는 메서드를 this와 바인딩(binding)하는 작업 필요

 

- 생성자 메서드에서 메서드 바인딩 작업

 

EventPractice.js

import { 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;

 

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

 

- 바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메서드 정의 

 

EventPractice.js

...
handleChange =(e) => {
        this.setState( {
            message:e.target.value
        });
    }

    handleClick = () => {
        alert(this.state.message);
        this.setState ( {
            message:''
        });
    }
...

 

3) input 여러 개 다루기 

 

- onChange 이벤트 핸들러에서 e.target.name은 해당 인풋의 name을 가리킴 

 

EventPractice.js

import { 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;

 

 

 

4) onKeyPress 이벤트 핸들링 

 

- comment 인풋에서 enter를 눌렀을 때 handleClick 메서드를 호출

 

EventPractice.js

 

import { 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: ''
        });
    }

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

    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}
                    onKeyPress={this.handleKeyPress}
                />
                <button onClick={this.handleClick}> 확인</button>
            </div>
        )
    }
}

export default EventPractice;

 

 

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

 

- e.target.name을 활용하지 않고 onChage 관련 함수 두 개를 따로 만듬

 

EventPracitce.js

import { 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}
                onChnage={onChangeMessage}
                onKeyPress={onKeyPress}
            />
            <button onClick={onClick}>확인</button>
        </div>
    )
}

export default EventPractice;