1. 리액트의 이벤트 시스템
리액트의 이벤트 시스템은 웹 브라우저의 HTML 이벤트와 인터페이스가 동일하기 때문에 사용법이 꽤 비슷함
2. 이벤트를 사용할 때 주의 사항
1. 이벤트 이름은 카멜 표기법으로 작성
HTML: onclick -> React: onClick
2. 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달한다.
- 화살표 함수 문법으로 함수를 만들어 전달
- 렌더링 부분 외부에 미리 만들어 전달
3. DOM 요소에만 이벤트를 설정할 수 있음
- DOM 요소에는 이벤트를 설정할수 있지만 컴포넌트에는 이벤트를 자체적으로 설정할 수 없음
3. 이벤트 종류
몇가지만 정리 해봤다.
나머지 이벤트는 리액트 매뉴얼
(http://facebook.github.io/react/docs/events.html) 참고를 하면 된다.
Clipboard | Composition | Keyboard | Focus | Form | Mouse | Selection |
Touch | UI | Wheel | Media | Image | Animation | Transition |
4. 예제로 이벤트 핸들링 익히기
컴포넌트 생성(클래스형 컴포넌트)
import React, { Component } from 'react';
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
</div>
);
}
}
export default EventPractice;
App.js에서 EventPractice 렌더링
import React from "react";
import EventPractice from "./EventPractice";
const App = () => {
return <EventPractice />;
};
export default App;
5. onChange 이벤트 핸들링하기
onChange 이벤트 설정
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
onChange={(e) => {
console.log(e);
}}
></input>
</div>
);
}
}
여기서 e객체는 syntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체다. 네이비트 이벤트와 인터페이스가 같으므로 순수 자바스크립트에서 HTML 이벤트를 다룰 때와 똑같이 사용하면 된다.
onChange={(e) => console.log(e)}
콘솔에 기록되는 e 객체는 SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체
네이티브 이벤트와 인터페이스가 같으므로 순수 JS에서 HTML 이벤트를 다룰때와 똑같이 사용하면 됨
SyntheticEvent는 네이티브 이벤트와 달리 이벤트가 끝나고 나면 이벤트가 초기화되므로 정보를 참조할 수 없음
예를 들어 0.5초뒤에 e객체를 참조하면 e객체 내부의 모든 값이 비워지게 됨
만약 비동기적으로 이벤트 객체를 참조할 일이 있다면 e.persist() 함수를 호출해 주어야 함
6. state에 input 값 담기
생성자 메서드 인 constructor에서 state 초깃값을 설정하고, 이벤트 핸들링 함수 내부에서 this.setState 메서드를 호출하여 state를 업데이트 한다.
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,
});
}}
></input>
</div>
);
}
7. 버튼을 누를 때 comment 값을 공백으로 설정
render() {
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={this.state.message}
onChange={(e) => {
this.setState({
message: e.target.value,
});
}}
></input>
<button
onClick={() => {
alert(this.state.message);
this.setState({
message: "",
});
}}
>
확인
</button>
</div>
);
}
input 요소 코드 아래쪽에 button을 하나 만들고, 클릭 이벤트가 발생하면 현재 comment 값을 메세지 박스로 띄운 후 comment 값을 공백으로 설정
8. 임의 메서드 만들기
이벤트의 실행할 자바스크립트 코드를 전달하는 것이 아닌, 함수형태의 값을 전달해야되기 때문에
이벤트를 처리할 때 렌더링을 하는 동시에 함수를 만들어서 전달했음
이 방법 대신 함수를 미리 준비하여 전달하는 방법도 있음. 성능상으로는 차이가 거의 없지만 가독성을 훨씬 높음
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}
></input>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어져 버림
임의 메서드가 이벤트로 등록되어도 this를 컴포넌트 자신으로 제대로 가리키기 위해서는 메서드를 this와 바인딩하는 작업이 필요함. 바인딩하지 않는 경우, this가 undefined를 가리키게 됨
9. Property Initializer Syntex를 사용한 메서드 작성
메서드 바인딩은 생성자 메서드에서 하는것이 작성이나 이 작업을 좀 더 간단하게 하는 방법이 있음
바벨 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메서드를 정의하는 것
state = { message: "" };
handleChange = (e) => {
this.setState({
message: e.target.value,
});
10. input 여러 개 다루기
input이 여러개일때는 메서드를 여러개 만드는 방법도 있지만 event 객체를 활용하면 더 쉽게 처리할 수 있음
e.target.name값을 사용하면 됨 onChange 이벤트 핸들러에서 e.target.name은 인풋의 name을 가리킴.
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>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={this.state.message}
onChange={this.handleChange}
></input>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
여기서는 이 코드가 핵심이다.
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
// 여기서는 username, message가 들어감
});
};
객체 안에서 key를 [ ]로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key값으로 사용된다.
// 예시
const name = 'variantKey'
const object = {
[name]: 'value'
}
// 결과
{
'VariantKey': 'Value'
}
11. onKeyPress 이벤트 핸들링
키를 눌렀을때 발생하는 KeyPress 이벤트를 처리하는 방법
comment 인풋에서 Enter를 눌렀을때 handleClick 메서드를 호출
import React, { Component } from "react";
class EventPractice extends Component {
state = { username: "", message: "" };
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
// 여기서는 username, message가 들어감
});
};
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>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요"
value={this.state.message}
onChange={this.handleChange}
onKeyPress={this.handleKeyPress}
></input>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
12 . 함수 컴포넌트로 구현해 보기
함수형 컴포넌트로 똑같이 구현하기
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}
onChange={onChangeMessage}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPractice;
input이 2개라서 onChange 관련 함수 두개를 만들었지만 인풋이 개수가 많아진다면 더 많은 함수가 필요하기에 개수가 많을수록 e.target.name을 활용하는 것이 더 좋을 수 있음
useState를 통해 사용하는 상태에 문자열이 아닌 객체를 넣는 방식
import { 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}
/>
<input
type='text'
name='message'
placeholder='아무거나 입력하셈'
value={message}
onChange={onChange}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPractice;
e.target.name 값을 활용하려면, 위와 같이 useState를 쓸 때 인풋 값들이 들어 있는 form 객체를 사용하면 된다.
13. 정리
리액트에서 이벤트를 다루는 것은 순수 JS 또는 jQuery를 사용한 웹 애플리케이션에서 이벤트를 다루는 것과 비슷함
리액트의 장점 중 하나는 JS에 익숙하다면 쉽게 활용할 수 있다는 점
기존 HTML DOM Event를 알고 있다면 리액트의 컴포넌트 이벤트도 쉽게 다룰 수 있다.
클래스형 컴포넌트로 할 수 있는 대부분의 작업은 함수형 컴포넌트로도 구현할 수 있다.
함수형 컴포넌트에서는 useReducer와 커스텀 Hooks를 사용하게 된다면 이 작업을 훨씬 편하게 할 수 있다.
'React > 다시 공부하는 리액트' 카테고리의 다른 글
다시 공부하는 리액트 6장 컴포넌트 반복 (0) | 2023.07.04 |
---|---|
다시 공부하는 리액트 5장 ref.DOM 이름 달기 (0) | 2023.07.04 |
다시 공부하는 리액트 3장 component, state (0) | 2023.07.02 |
7장. 컴포넌트의 라이프사이클 메서드 (0) | 2023.06.22 |
6장. 컴포넌트 반복 (0) | 2023.06.21 |