사용자가 웹 브라우저에서 DOM 요소들과 상호작용 하는 것을 이벤트라고 한다. HTML을 통해 주로 설정되지만 리액트에서도 작성할 수 있다.
리액트 이벤트 시스템
리액트의 이벤트 시스템은 HTML로 작성한 이벤트와 인터페이스가 동일하므로 사용법이 비슷하다. 따라서 HTML에서 작성하던 것처럼 작성하되 몇가지 주의해야할 사항이 있다.
- 이벤트 이름은 카멜 표기법으로 작성한다.
HTML : [onclick. onkeyup]
react : [onClick, onKeyUp]
- 이벤트에는 자바스크립트 코드 전달이 아닌 함수 형태의 값을 전달한다.
함수 형태의 값은 여러가지 형식이 허용된다.
- DOM 요소에만 이벤트를 적용할 수 있다.
즉, div, button, input, form, span 등의 DOM 요소에만 이벤트가 설정이 가능하고, 직접 만든 컴포넌트에서는 이벤트를 자체적으로 설정할 수 없다. 직접 만든 컴포넌트에 이벤트 요소처럼 값을 넣는것은, 이벤트 요소와 이름이 같은 props를 컴포넌트로 전달해주는 형식이 되기 때문이다.
그러므로 직접 만든 컴포넌트에 이벤트 요소를 넣고 싶다면, props 형태로 이벤트를 받아서 컴포넌트 내부에서 DOM 이벤트를 설정하기도 한다.
이벤트 종류
이벤트 종류는 다음과 같다
- Clipboard
- Composition
- Keyboard
- Focus
- Form
- Mouse
- Selection
- Touch
- UI
- Wheel
- Media
- Image
- Animation
- Transition
이벤트 핸들링 익히기
컴포넌트 생성
새로운 컴퍼넌트를 하나 만들어 본다.
// src/EventPractice.tsx
import { useState } from "react";
function EventPractice() {
return (
<div>
<h1>이벤트 연습</h1>
</div>
);
}
export default EventPractice;
// src/App.tsx
import React from "react";
import "./App.css";
import { Component } from "react";
import EventPractice from "./EventPractice";
class App extends Component {
render() {
return <EventPractice />;
}
}
export default App;
여기서 input 요소를 렌더링하는 코드와 onChange 이벤트를 설정하는 코드를 작성한다.
import { useState } from "react";
function EventPractice() {
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
onChange={(e) => {
console.log(e.target.value);
}}
/>
</div>
);
}
export default EventPractice;
이렇게 작성해주면, 입력칸에 입력을 할 때마다, 페이지 검사에서 콘솔에 값이 기록되는것을 확인할 수 있다.
이제, 이 입력값을 state에 담아보고자 한다. useState를 통해 state를 업데이트 하고, 실시간으로 화면에 나타낼 수 있도록 만들 수 있다.
import { useState } from "react";
function EventPractice() {
const [message, setMessage] = useState("");
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
onChange={(e) => {
setMessage(e.target.value);
}}
/>
<h1>{message}</h1>
</div>
);
}
export default EventPractice;
이렇게 작성해주면, 입력칸에 입력된 값이 e.target.value에 저장되고, 그것을 message에 업데이트 해줄 수 있다.
다음은 버튼을 만들어서 메세지를 알림으로 띄운 뒤, 클릭 이벤트가 발생하면 입력칸을 공백으로 설정하도록 해보자.
import { useState } from "react";
function EventPractice() {
const [message, setMessage] = useState("");
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
value={message}
onChange={(e) => {
setMessage(e.target.value);
}}
/>
<button
onClick={() => {
alert(message);
setMessage("");
}}
>
확인
</button>
<h1>{message}</h1>
</div>
);
}
export default EventPractice;
이런식으로 버튼을 추가해주었다. 버튼을 누르게되면, 입력한 메세지가 알림으로 뜨고, 메세지를 공백으로 업데이트 시켜서 입력칸도 비워주는 동작을 수행한다.
마지막으로 임의의 메서드를 만들어보자. 이벤트의 주의사항에서 이벤트에 실행할 자바스크립트 코드가 아닌, 함수 형태의 값을 전달 한다고 했었다. 따라서 이벤트 처리 시 렌더링을 하는 동시에 함수를 만들어서 전달해주었다. 이 방법보다 함수를 미리 준비해서 전달하는 방법도 있다. 성능상의 차이는 거의 없으나 가독성이 매우 높아지기 때문에 사용하는것도 좋다.
아래 코드는 위 코드의 이벤트들을 메서드로 만들어서 전달해주는 방식으로, 같은 동작을 수행한다.
import { useState } from "react";
function EventPractice() {
const [message, setMessage] = useState("");
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setMessage(e.target.value);
}
function handleClick() {
alert(message);
setMessage("");
}
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
value={message}
onChange={handleChange}
/>
<button onClick={handleClick}>확인</button>
<h1>{message}</h1>
</div>
);
}
export default EventPractice;
이런식으로 임의의 메서드를 사용해주면 이벤트 핸들링 시 더 높은 가독성의 코드를 작성할 수 있다.
다음은 input이 두 개 이상일 경우이다. 이럴 경우, 메서드를 여러개 만들기보다 event 객체를 활용해서 각각의 프로퍼티를 가리킬 수 있다.
위의 코드를 수정해서 두 개의 입력값을 받을 수 있게 만들어주었다.
import { useState } from "react";
function EventPractice() {
const [userName, setUserName] = useState("");
const [message, setMessage] = useState("");
function handleChangeUserName(e: React.ChangeEvent<HTMLInputElement>) {
setUserName(e.target.value);
}
function handleChangeMessage(e: React.ChangeEvent<HTMLInputElement>) {
setMessage(e.target.value);
}
function handleClick() {
alert(userName + " : " + message);
setMessage("");
setUserName("");
}
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="userName"
placeholder="사용자 이름"
value={userName}
onChange={handleChangeUserName}
/>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
value={message}
onChange={handleChangeMessage}
/>
<button onClick={handleClick}>확인</button>
</div>
);
}
export default EventPractice;
마지막으로, 확인 버튼을 마우스로 클릭하는 것이 불편할 수 있기 때문에, 특정 키의 입력을 이벤트로 발생시키는 KeyPress 이벤트를 작성해보도록 한다. 두번째 입력을 받을 경우에 Enter 키를 이벤트로 받도록 코드를 작성해보자.
import { useState } from "react";
function EventPractice() {
const [userName, setUserName] = useState("");
const [message, setMessage] = useState("");
function handleChangeUserName(e: React.ChangeEvent<HTMLInputElement>) {
setUserName(e.target.value);
}
function handleChangeMessage(e: React.ChangeEvent<HTMLInputElement>) {
setMessage(e.target.value);
}
function handleClick() {
alert(userName + " : " + message);
setMessage("");
setUserName("");
}
function handleKeyPress(e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter") handleClick();
}
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="userName"
placeholder="사용자 이름"
value={userName}
onChange={handleChangeUserName}
/>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
value={message}
onChange={handleChangeMessage}
onKeyPress={handleKeyPress}
/>
<button onClick={handleClick}>확인</button>
</div>
);
}
export default EventPractice;
마지막으로, 코드의 가독성을 위해 handleChange 함수들을 하나로 합쳐보고자 한다. 이것은 순전히 취향으로 선택하기를 바란다. 현재의 경우 2개의 인풋이므로 합쳐도 좋지만, 인풋이 많아질 수록 하나씩 함수를 만들어주는 것이 더 좋은 방법일 수 있다.
import { useState } from "react";
function EventPractice() {
const [form, setForm] = useState({
userName: "",
message: "",
});
const { userName, message } = form;
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const nextForm = {
...form,
[e.target.name]: e.target.value,
};
setForm(nextForm);
}
function handleClick() {
alert(userName + " : " + message);
setForm({ userName: "", message: "" });
}
function handleKeyPress(e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter") handleClick();
}
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="userName"
placeholder="사용자 이름"
value={userName}
onChange={handleChange}
/>
<input
type="text"
name="message"
placeholder="아무거나 입력해 보세요."
value={message}
onChange={handleChange}
onKeyPress={handleKeyPress}
/>
<button onClick={handleClick}>확인</button>
</div>
);
}
export default EventPractice;
두 개의 handleChange 함수들을 하나로 합친 모습이다. 두 개로 따로 사용할 때와 동일한 동작을 수행한다.
'WEB > React' 카테고리의 다른 글
리액트 컴포넌트 반복 사용하기 [react/component/typescript] (0) | 2023.03.12 |
---|---|
리액트 DOM 네이밍 이해하기 (0) | 2023.03.12 |
리액트 컴포넌트 이해하기 [react/component/typescript] (0) | 2023.03.11 |
JSX 이해하기 (0) | 2023.03.11 |
리액트 이해하기 (0) | 2023.03.11 |