이벤트란 웹브라우저에서 사용자 혹은 개발자로 인해 발생하는 HTML 요소에 대한 사건의 발생을 말한다.
우리는 js를 공부하며 HTML로 열심히 만든 요소들이 여러 이벤트에 따라 특정한 동작으로 알맞은 반응을 하도록 열심히 이벤트 처리를 해줬다.
리액트 또한 이런저런 컴포넌트를 만들어 UI를 구성했는데 이 요소들이 이벤트 처리가 되지 않으면 아무 의미가 없기 때문에 당연히 이벤트 처리가 필수적이다!
이벤트는 js에서의 이벤트와 거의 같기때문에 새로운것을 공부할 필요는 없다. 가벼운 마음으로 리액트에서의 이벤트에 대해 정리해보자.
이벤트의 종류 자체는 따로 정리할것도 없는게 리액트에서의 DOM 이벤트 자체는 js와 마찬가지로 onclick, onsubmit, onchange, onfocus 등등.. 다 아는 것들이다.
중요한건 리액트에서는 < on + 이벤트명 > 네이밍 시, 카멜케이스를 사용한다는 것이다. 따라서
onClick, onSubmit, onChange, onFocus 등등.. on 뒤의 이벤트명은 첫글자를 대문자로 적어줘야 한다.
리액트에서의 이벤트 처리 방법은 크게 두가지로 나눌 수 있다.
컴포넌트 내에서 이벤트 핸들링 함수를 선언해놓고 Element에 넘겨주는 방식이다.
function App() {
function handleClick() {
alert("클릭함");
}
return (
<div>
<button onClick={handleClick}>버튼</button>
</div>
)
}
이렇게 이벤트 핸들링 함수를 따로 선언해두고 Element에서 이벤트 처리기 속성에 그 함수를 지정해주면 된다. 물론 함수 자체를 지정하는거니 괄호 빼고 함수명만 입력하는것은 당연!
※ 함수명 뒤에 괄호를 붙이면 그 함수를 실행하라는것, 즉 함수 '호출'의 의미가 된다.
※ 이벤트 핸들링 함수의 함수명은 보통 < handle + 이벤트명 >로 짓는다.
Element의 이벤트 처리기 속성에서 함수를 즉석으로 생성해 지정해줄 수도 있다.
function App() {
return (
<div>
<button onClick={ () => {alert("클릭함");} }>버튼</button>
</div>
)
}
핸들링 함수가 간단하다면 간편하게 익명함수로 바로 처리해주는것도 좋을듯하다.
DOM Element에서 이벤트가 발생하면 이벤트 처리기에 지정된 핸들링 함수로 '이벤트 객체' 라는것이 전달된다.
이벤트 객체에는 어떤 요소에서 이벤트가 발생했는지, 어떤 종류의 이벤트가 발생했는지 등 이벤트에 대한 정보들이 들어있다.
따라서 핸들링 함수에서 이벤트 객체를 이용해 다양한 처리를 해줄 수 있다.
function App() {
function handleClick(e) {
console.log(`님이 입력한 내용 : ${e.target.value}`);
}
return (
<div>
<input onChange={handleClick} />
</div>
)
hadleClick 함수의 매개변수인 e가 이벤트 객체이다(보통 event 혹은 e 라는 이름으로 짓는다).
이벤트 객체의 프로퍼티중 target 이라는 애가 있는데 이벤트가 발생한 대상을 반환해주는 친구다. 따라서 e.target은 이벤트가 발생한 input 태그가 되고 input 태그의 value는 input 태그에 입력한 텍스트 값이니 e.target.value 하면 input 태그에 입력한 값이 된다.
e.target.value는 거의 공식처럼 자주 쓰이는 표현 중 하나다.
const App() {
const [name, setName] = useState("개똥이");
return (
<div>
<h1>{name}님 안녕</h1>
<MyForm onChange={() => {setName("돌쇠")}} />
</div>
);
}
이벤트 처리기 또한 props로 전달이 가능하다. 이처럼 사용자 정의 컴포넌트에 이벤트를 지정하면 아래와 같이 해당 컴포넌트의 선언부에서 props로 그 이벤트의 핸들링 함수를 받아 처리할 수 있다.
const MyForm = ({ onChange }) => {
return (
<div>
<span>이름 : </span>
<input onChange={onChange} />
</div>
);
}
App의 MyForm 컴포넌트에서 onChange에 () => {setName("돌쇠")} 라는 함수를 지정했으니 MyForm의 선언부에서 props로 받은 onChange는 () => {setName("돌쇠")} 라는 함수인 것이다.
그리고 input의 onChange 이벤트 처리기를 담당하는 핸들링 함수로 이 onChange 함수를 지정한 상황이다. 이름은 같지만 첫번째 onChange는 단순히 이벤트 처리기 속성명이고 두번째 onChange가 상위 컴포넌트에서 전달받은 핸들링함수이다!
정해진 이벤트들 뿐만 아니라 사용자가 직접 이벤트를 정의할 수 있다.
const App = () => {
const [name, setName] = useState("개똥이");
return (
<div>
<h1>{name}님 안녕</h1>
<MyForm onRename={(e) => {setName(e.target.value)}} />
</div>
);
}
const MyForm = ({ onRename }) => {
const handleRename = (e) => {
console.log(e.target.value)
if (e.target.value.includes("-")) {
alert("이름에 - 안됨");
return;
}
onRename(e);
}
return (
<div>
<span>새로운 이름</span>
<input onChange={handleRename} />
</div>
);
}
직접 이벤트를 만든 예시다. 커스텀 이벤트를 설명하기위해 굉장히 조잡하게 만들었다.
input창에 적는 이름으로 현재 state 변수인 name을 수정하여 이름을 바꾸는데 이름에 "-" 문자가 들어가면 alert 창을 띄우는 이벤트를 onRename 이라는 이름으로 하나 만든 것이다.
구현은 컴포넌트간 이벤트 전달 파트에서 설명한 예시와 동일하게 props로 이벤트를 전달하여 만든 것이다.
아무튼 중요한건 이처럼 나만의 이벤트를 직접 만들수도 있다는 것이다.