이벤트 핸들링
- 사용자가 웹 브라우저에서 DOM 요소들과 상호 작용하는 것
- onmouseover, onclick, onchange 등
이벤트를 사용할 때 주의사항
1. 이벤트 이름은 카멜 표기법으로 작성한다
- onclick (X) onClick(O)
- onkeyup(X) onKeyUp(O)
2. 이벤트에는 함수 형태의 값을 전달한다
- 실행할 자바스크립트 코드를 직접 전달하지 않고, 함수 형태의 객체를 전달한다
- 화살표 함수를 바로 만들어 전달해도 되고, 렌더링 부분 외부에 미리 만들어서 전달해도 된다
3. DOM 요소에만 이벤트를 설정할 수 있다
- div, button, input, form, span 등의 요소에는 DOM 이벤트를 설정할 수 있다
- 하지만 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없다
- ex) MyComponent에 onClick 값을 설정해도 그냥 이름이 onClick 인 props를 전달하는 것 뿐
- 전달받은 props를 컴포넌트 내부의 DOM 이벤트로 설정하는 것은 가능
- ex) <div onClick={this.props.onClick}>{...}</div>
이벤트 종류
Clipboard | Touch | Composition | UI | Keyboard |
Wheel | Focus | Media | Form | Image |
Mouse | Animation | Selection | Transition |
이벤트 핸들링 실습
실습 순서
- 컴포넌트 생성 및 불러오기
- onChange 이벤트 핸들링하기
- 임의 메서드 만들기
- input 여러개 다루기
- onKeyPress 이벤트 핸들링하기
1. 컴포넌트 생성 및 불러오기
1-1. 컴포넌트 생성
import React, { Component } from 'react';
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
</div>
);
}
}
export default EventPractice;
1-2. App.js에서 EventPractice 렌더링
//App.js
import EventPractice from './EventPractice';
const App = () => {
return <EventPractice />;
};
export default App;
2. onChange 이벤트 핸들링하기
2-1. onChange 이벤트 설정
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 : 웹 브라우저의 네이티브 이벤트를 감싸는 객체
- 네이티브 이벤트와 달리 이벤트가 끝나고 나면 이벤트가 초기화 되므로 정보를 참조할 수 없게 된다
- 즉, 0.5초 뒤에 e 객체를 참조하면 e 객체 내부의 모든 값이 비워진 상태가 된다
- 그러므로 만약 비동기적으로 이벤트 객체를 참조할 일이 있다면 e.persist() 함수를 호출해야 한다
- input 상자의 변경사항 기록 : e.target.value
onChange={(e) => {
console.log(e.target.value);
}}
2-2. state에 input값 담기
- 생성자 메서드인 constructor에서 state 초기값을 설정하고 이벤트 핸들링 함수 내부에서 this.setState 메서드를 호출하여 state를 업데이트 해보기
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,
});
}}
/>
</div>
);
}
}
export default EventPractice;
- 오류 안나면 성공
2-3 버튼을 누를 때 comment 값을 공백으로 설정
- input comment 값을 alert로 띄운 후 comment를 공백으로 초기화
import React, { Component } from 'react';
class EventPractice extends Component {
state = {
message: '',
};
render() {
return (
<div>
<h1>이벤트 연습</h1>
<input (...)/>
<button
onClick={() => {
alert(this.state.message);
this.setState({
message: '',
});
}}
>
확인
</button>
</div>
);
}
}
export default EventPractice;
3. 임의 메서드 만들기
3-1. 기본 방식
- 이벤트에는 함수 형태의 값을 전달하도록 되어있다
- 이벤트를 처리할 때 동시에 함수를 만들어서 전달해도 되지만 미리 준비해서 전달하면 가독성이 높다
- this bind
- 함수가 호출될 떄 this는 호출부에 따라 결정되기 때문에 클래스의 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어진다.
- this가 컴포넌트 자신으로 올바르게 가리키기 위해서는 메서드와 this를 바인딩 해야한다(안하면 this가 undefined로 됨)
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
}
- 이벤트 핸들링할 때 미리 만든 임의 메서드로 수정
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>9
<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-2. Property Initializer Syntax를 사용한 메서드
- 기본 방식은 새 메서드를 만들 때마다 constructor도 수정해야 해서 번거롭다
- 바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메서드를 정의하면 더 간편하다
class EventPractice extends Component {
state = {
message: '',
};
handleChange = (e) => {
this.setState({
message: e.target.value,
});
};
handleClick = () => {
alert(this.state.message);
this.setState({
message: '',
});
};
4. input 여러 개 다루기
- input이 여러개일 경우 event 객체를 활용할 수 있다
- 객체 안에서 key를 [ ]로 감싸면 그 안에 넣은 레퍼런스의 실제 값이 key로 사용된다
const name = 'variantKey'
const object = {
[name] : 'value'
}
// 결과 : 'variantKey' : 'value'
- handlerChange의 역할
- input에는 둘 다 name 속성이 있다
- e.target.name을 사용하여 어떤 입력 필드가 변경되었는지 동적으로 알아내고, 그에 맞는 상태값(this.state.username 또는 this.state.message)를 업데이트 한다
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: '',
});
};
전체 코드
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}
/>
<br />
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={this.state.message}
onChange={this.handleChange}
/>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
결과
5. onKeyPress 이벤트 핸들링
- Enter 키를 눌렀을 때 handleClick 메서드가 실행
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: '',
});
};
// 추가
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}
/>
<br />
<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;
결과
onKeyPress 변경사항
- 표준화된 이벤트가 아니기 때문에 브라우저마다 동작이 다를 수 있어 사용 중단 예정이다
- onKeyDown(키를 누를 때), onKeyUp(키를 뗄 때) 로 대체되었다
함수 컴포넌트로 구현해보기
- e.target.name을 사용하지 않고 onChange 관련 함수 두 개를 따로 만들어준 버전
- input이 적을 땐 위와같이 해도 괜찮지만, input이 많아지면 e.target.name을 활용하는 것이 더 편하다
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}
/>
<br />
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={message}
onChange={onChangeMessage}
onKeyPress={onKeyPress} // 추가
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPractice;
결과
- useState에 문자열이 아닌 객체를 활용하는 방법
- e.target.name 값을 활용하려면, 아래와 같이 useState를 쓸 때 인풋 값들이 들어 있는 form 객체를 사용하면 됨
import React, { useState } from 'react';
const EventPractice = () => {
const [form, setForm] = useState({
username: '',
message: '',
});
const { username, message } = form;
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}
/>
<br />
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={message}
onChange={onChange}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPractice;
결과 같음
'개발새발개발 > React' 카테고리의 다른 글
React - 컴포넌트 반복(map, callback, key, list, 값 추가 삭제) (1) | 2024.12.30 |
---|---|
React - ref (0) | 2024.12.29 |
React state, 클래스형 컴포넌트와 함수형 컴포넌트에서의 state와 주의사항 (0) | 2024.12.25 |
React 컴포넌트(Component), 화살표 함수, Snippet (1) | 2024.12.24 |
React JSX 문법과 ESLint, Prettier 적용법 (0) | 2024.12.23 |
댓글