1. 이벤트 핸들링(Event Handling)이란?
사용자가 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트(event)라고 합니다.예를 들어 버튼에 마우스 커서를 올렸을 때는 onmouseover 이벤트를 실행, 클릭했을 때는 onclick 이벤틀를 실행, Form 요소는 값일 바뀔 때 onchange 이벤트를 실행합니다.리액트에서의 이벤트 시스템은 이러한 HTML에서 DOM요소에 이벤트를 설정하는 방법과 매우 유사합니다.그럼 한번 살펴 봅시다.
2. 리액트의 이벤트 시스템
리액트의 이벤트 시스템은 웹 브라우저의 HTML 이벤트와 인터페이스가 동일하기 때문에 사용법이 꽤 비슷합니다.아래에서 살펴 봅시다.
import React, { useState } from "react";
function App() {
const [message, setMessage] = useState("");
const onClickEnter = () => {
setMessage("안녕하세요!");
};
const onClickLeave = () => {
setMessage("안녕히 가세요!");
};
const [color, setColor] = useState("black");
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
</div>
(...)
);
}
export default App;
3. 이벤트를 사용할 때 주의 사항
1) 이벤트 이름은 카멜 표기법으로 작성합니다.
- Ex ) onclick => onClick , onkeyup => onKeyUp
2) 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달합니다.
- HTML에서 이벤트를 설정할 때는 큰따옴표 안에 실행할 코드를 넣었지만, 리액트에서는 함수 형태의 객체를 전달해야 합니다.
3.) DOM 요소에만 이벤트를 설정할 수 있습니다.
- 즉 div, button, input, form, span 등의 DOM 요소에는 이벤트를 설정할 수 있지만, 우리가 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없습니다.
- Ex ) <MyComponent onClick={doSomething} /> ==> X , <div onClick={this.props.onClick}>{ /* (...) */ } </div> ==> O
4. 이벤트 종류
리액트에서 지원하는 이벤트 종류는 다음과 같습니다.
- Clipboard
- Touch
- Compositon
- UI
- Keyboard
- Wheel
- Focus
- Media
- Form
- Image
- Mouse
- Animation
- Selection
- Transition
5. onClick, onChange, onKeyPress
위에서 볼 수 있는것과 같이 이벤트에는 많은 종류가 있지만 본문에서는 위의 대표적인 이벤트만 다뤄 보겠습니다.
1) useState + onClick
우리가 어떤 버튼을 만들고 그것을 클릭했을 때 state를 변경하는 것을 만들어 볼게요.
먼저 버튼을 만들어볼까요? <button> 태그를 이용해서 버튼을 생성합니다.
// src/App.js
import React from "react";
function App() {
return (
<div>
<button>버튼</button>
</div>
);
}
export default App;
버튼은 누르라고 있는 것이죠!
우리는 이 버튼을 눌렀을 때 하고 싶은 행동을 함수로 만들 수 있습니다. 아래 코드와 같이 onClickHandler 라는 함수를 만들고 onClick={} 에 넣어주었습니다. React에서는 이러한 방식으로 함수와 컴포넌트(button 태그)를 연결시킵니다.
우리는 이 함수를 이벤트 핸들러 라고 표현합니다. 함수에 console.log("hello button"); 라는 코드를 작성하고 버튼을 누른 후 콘솔을 봅시다. 우리가 만든 함수로 인해 버튼을 누를 때 마다 콘솔에 hello button 이 찍히는 것이 보입니다.
import React from "react";
function App() {
// 버튼을 눌렀을 때 하고 싶은 행동
function onClickHandler() {
console.log("hello button");
}
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
1-2) state 구현하고 이벤트 핸들러와 연결하기
우선 state를 하나 만듭니다. 그리고 이 버튼을 클릭을 했을 때 state 값을 바꿔보겠습니다. 이벤트 핸들러를 만들어주고 그 안에 setName 을 넣어줍니다.
이제 우리가 버튼을 누르면 setName()안에 있는 값이 “누렁이”니까, state가 “길동이"에서 “누렁이”로 바뀌겠군요!
import React, { useState } from "react";
function App() {
const [name, setName] = useState("길동이");
function onClickHandler() {
setName("누렁이");
}
return (
<div>
{name}
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
export default App;
2) useState + onChange
input에서는 보통 사용자가 입력한 값을 state로 관리하는 패턴을 많이 사용합니다. 아래 코드를 봐주세요.
import React, { useState } from "react";
const App = () => {
const [value, setValue] = useState("");
return (
<div>
<input type="text" />
</div>
);
};
export default App;
input과 useState를 사용해서 input의 값을 넣을 value라는 state를 생성했습니다. 이번에는 function keyword를 사용하지 않고 화살표 함수를 사용해보았어요.
2-1) 이벤트핸들러를 구현하고 state와 연결하기
input과 생성한 state(value)를 연결해볼게요.
먼저 input에 onChange라는 이벤트를 불러내고, 우리가 생성한 이벤트 핸들러 함수를 넣습니다. 함수는 아래 코드 처럼 작성합니다.
import React, { useState } from "react";
const App = () => {
const [value, setValue] = useState("");
const onChangeHandler = (event) => {
const inputValue = event.target.value;
setValue(inputValue);
};
console.log(value) // value가 어떻게 변하는지 한번 콘솔로 볼까요?
return (
<div>
<input type="text" onChange={onChangeHandler} value={value} />
</div>
);
};
export default App;
그리고 우리는 이벤트 핸들러 안에서 자바스크립트의 event 객체를 꺼내 사용할 수 있습니다. 사용자가 입력한 input의 값은 event.target.value 로 꺼내 사용할 수 있죠. 마지막으로 state인 value를 input의 attribute인 value에 넣어주면 input과 state 연결하기, 끝 입니다!
3) onKeyUp
이번에는 키를 눌렀을 때 발생하는 keyUp 이벤트를 처리하는 방법을 알아보겠습니다. 인풋에서 Enter를 눌렀을 때 handleClick 메서드를 호출하도록 코드를 작성해 봅시다.
import React, { useState } from "react";
function App() {
const [username, setUsername] = useState("");
const [message, setMessage] = useState("");
const onChangeUsername = (event) => {
setUsername(event.target.value);
};
const onChangeMessage = (event) => {
setMessage(event.target.value);
};
const onClick = () => {
alert(username + ": " + message);
setUsername("");
setMessage("");
};
const onKeyPress = (event) => {
if (event.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}
onKeyUp={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
}
export default App;
두 번째 텍스트 인풋에서 텍스트를 입력하고 Enter key를 누르면 onClick 메서드가 실행되며 인풋값이 입력됩니다.
6. input 여러 개 다루기
우리는 input 값을 state에 넣는 방법을 배웠습니다. 하지만 input이 여러 개일 때는 어떻게 작업할까요? 메서드를 여러 개 만들어야 할까요? 물론 그것도 하나의 해법이기는 합니다만, 더 쉽게 처리하는 방법이 있습니다.
바로 event 객체를 활용하는 것입니다. e.target.name 값을 사용하면 됩니다. onChange 이벤트 핸들러에서 e.target.name은 해당 인풋의 name을 가리킵니다. 지금은 message 겠죠? 이 값을 사용하여 state를 설정하면 쉽게 해결할 수 있습니다.
코드를 한번 살펴봅시다.
function App() {
const [form, setForm] = useState({
username: "",
message: "",
});
const { username, message } = form;
const onChange = (event) => {
const nextForm = {
...form, // 기존의 form 내용을 이 자리에 복사한 뒤
[event.target.name]: event.target.value, // 원하는 값을 덮어 씌우기
};
setForm(nextForm);
};
const onClick = () => {
alert(username + ": " + message);
setForm({
username: "",
message: "",
});
};
const onKeyUp = (event) => {
if (event.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}
onKeyUp={onKeyUp}
/>
<button onClick={onClick}>확인</button>
</div>
);
}
export default App;
event.target.name 값을 활용하려면, 위와 같이 uesState를 쓸 때 인풋 값들이 들어 있는 form 객체를 사용해 주면 됩니다.
7. 정리
리액트에서 이벤트를 다루는 것은 순수 자바스크립트 또는 jQuery를 사용한 웹 애플리케이션에서 다루는 것과 비슷합니다. 리액트의 장점 중 하나는 자바스크립트에 익숙하다면 쉽게 활용할 수 있다는 것입니다. 따라서 기존 HTML DOM Event를 알고 있다면 리액트의 컴포넌트 이벤트도 쉽게 다룰 수 있을 것입니다.