이벤트
사용자가 웹 브라우저에서 DOM 요소와 상호작용하는 것을 이벤트(event) 라고 한다. React는 JS를 기반으로 하고 있기 때문에 이벤트 역시 JS의 그것과 크게 다르지 않다.
함수형 컴포넌트
import React, { useState } from "react";
const Counter = () => {
const [number, setNumber] = useState(0);
const onClickNumber = () => setNumber(number + 1);
return (
<div>
<button onClick={onClickNumber}>+1</button>
</div>
);
};
export default Counter;
이전에도 우리는 button 엘리먼트의 onClick 속성을 이용하여, 버튼 클릭 시 이벤트가 발생하게 코드를 짠 적 있다. 이전에는 onClick 속성에 익명 화살표 함수를 바로 대입하였다면, 위처럼 이벤트 함수를 따로 정의한 뒤에 대입해도 된다.
이벤트 함수명은 camelCase를 사용하며, 위처럼 간단히 state를 변경하는 경우엔 on+이벤트명+state 명 과 같은 형식을 사용하지만 복잡한 로직이 있는 경우 handle+작업명 을 사용하는 것이 개발자 사이의 관례이다.
...
<MyComponent onClick={onClickNumber}> ... </MyComponent>
...
이벤트 설정은 DOM 요소에만 가능하며, 컴포넌트에는 직접적으로 설정이 불가능하다. 위와 같이 두면 단지 onClick 이라는 이름의 props가 설정될 뿐이다.
클래스형 컴포넌트
import React, { Component } from "react";
class Counter extends Component{
state = {
number:0
}
constructor(props){
super(props);
this.onClickNumber = this.onClickNumber.bind(this);
}
onClickNumber(e){
this.setState({
number: this.state.number + 1;
})
}
render(){
return (
<div>
<button onClick={this.onClickNumber}>+1</button>
</div>
);
}
}
export default Counter;
함수가 호출될 때 this는 호출부에 따라 결정된다. 클래스의 메서드가 특정 HTML요소의 이벤트로 등록되면 일반 함수처럼 등록되고, 이 때 해당 클래스의 인스턴스를 가리키는 this의 관계가 끊어져버린다. 따라서 클래스형 컴포넌트에서 이벤트를 처리할 클래스 메서드를 선언할 때에는, bind()함수를 이용하여 constructor에서 this가 계속 컴포넌트 인스턴스를 가리키도록 바인딩해야한다.
onClickNumber = (e) => {
this.setState({
number: this.state.number + 1;
})
}
바벨의 transform-class-properties 문법을 사용하면 constructor와 bind없이 간단하게 구현 가능하다. 이 문법을 사용하면 화살표함수 선언시점의 this를 캡처하여 사용하므로, 별도의 bind 없이도 안전하게 this를 사용할 수 있다.
event객체
import React, { useState } from "react";
const Counter = () => {
const [text, setText] = useState("");
return (
<div>
<div> {text} </div>
<input
type="text"
name="message"
placeholder="아무거나 입력해보세요"
onChange={(e) => {
setText(e.target.value);
}}
/>
</div>
);
};
export default Counter;
일반적으로 event를 사용할 때, 화살표 함수의 첫번째 매개변수는 SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 wrapper 객체이다. 이름은 크게 상관 없지만, 관례적으로 e 혹은 event 를 사용한다.
e의 target 프로퍼티는 이벤트가 발생한 DOM 요소를 나타내며, 그 요소의 value 프로퍼티는 입력필드의 을 의미한다. e.target.value는 굉장히 많이 사용하는 값이므로 암기해두도록 하자.
💡 React 이벤트의 참조
네이티브 이벤트와 달리 이벤트가 끝나면 초기화 되어 정보를 참고할 수 없으므로, 이후에 비동기적으로 참조하기 위해선 e.persist()함수를 호출해야 한다.
const handleChange = (e) => { e.persist(); // e 객체 유지 setTimeout(() => { console.log(e.target.value); // 비동기적으로 e 객체 사용 }, 1000); };
input이 여러개인경우
import React, { useState } from "react";
const Counter = () => {
const [messages, setMessages] = useState({
message: "",
message2: "",
});
const { message, message2 } = messages;
const handleChange = (e) => {
setMessages({
...messages,
[e.target.name]: e.target.value,
});
};
return (
<div>
<input
type="text"
name="message"
placeholder="아무거나 입력해보세요"
value={message}
onChange={handleChange}
/>
<input
type="text"
name="message2"
placeholder="아무거나 입력해보세요"
value={message2}
onChange={handleChange}
/>
</div>
);
};
export default Counter;
input 등 값이 변화하는 것을 감지하기 위해서는 onChange 속성을 사용한다.
JS 객체 안에서 key를 []로 감싸면 내부 레퍼런스가 가리키는 실제값이 key값으로 사용된다. e.target.name은 해당 DOM의 이름을 나타내는 프로퍼티로, 위와 같이 state의 key값을 각 DOM의 name 필드에 배분하여 사용할 수 있다.
키를 누를경우
handleKeyPress = (e) => {
if(e.key === 'Enter'){
this.handleClick();
}
}
키를 누를경우에는 onKeyPress 속성을 사용할 수 있으며, 이벤트 객체에선 e.key 프로퍼티를 사용할 수 있다.
'Web > React' 카테고리의 다른 글
[React] 3-3. 컴포넌트 반복 (1) | 2023.12.04 |
---|---|
[React] 5-1. ref (1) | 2023.12.04 |
[React] 3-2. state (1) | 2023.11.29 |
[React] 3-1. 컴포넌트와 props (0) | 2023.11.27 |
[React] 2-2. JSX (2) | 2023.11.27 |