● 리액트의 이벤트 시스템
⚬ 이벤트 사용시 주의할 점
- 이벤트 이름은 카멜 표기법으로 작성한다.
- onClick, onChange, onKeyUp•••
- 이벤트에는 함수 형태의 값을 전달한다.
- onClick={ ( ••• )=>{ ••• } }
- DOM 요소에만 이벤트를 설정할 수 있다.
- 컴포넌트에는 이벤트를 달 수 없다. <MyComponent onClick={~~~} > 이렇게 적으면 onClick인 props 를 전달해주는 것임
⚬ 이벤트 종류
- Clipboard
- Composition
- keyboard
- Focus
- Form
- Mouse
- Selection
- Touch
- UI
- Wheel
- Media
- Image
- Animation
- Transition
● onChange 이벤트 실습하기
⚬ 클래스 컴포넌트 실습
import { Component } from "react";
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트연습</h1>
<input
type="text"
name="message"
placeholder="아무거나 입력해보세요"
onChange={(e) => {
console.log(e.target.value);
}}
></input>
</div>
);
}
}
export default EventPractice;
input에 onChange 이벤트를 설정하고, e를 넣으면 이벤트 객체를 사용할 수 있습니다. 리액트에서는 SyntheticEvent 객체라고 합니다.
자바스크립트와 같이 똑같이 사용할 수 있습니다. 변하는 값을 캐치하려면 e.target.value로 써주면 됩니당!
onChange={(e) => {
this.setState({ message: e.target.value });
}}
입력할 때마다 값을 변경하게 하고 싶다면 위와 같이 적어주면 됩니다.
만약에 이벤트 핸들러에 미리 함수를 저장해서 전달하고 싶다면?
constructor 바깥에서 메서드로 설정해줍니다. 그런데 this 바인딩을 꼭 해주어야함 왜냐면 이벤트 핸들러의 this 바인딩이 풀리기 때문에 내부 constructor에서 bind 를 해주어야한다 그말입니다. . 왜냐면 이벤트를 감지하는 이벤트 핸들러 즉, 콜백함수로 들어갔기 때문임. 그래서 this 바인딩을 잃어버린 것입니다.
⚬ 클래스 컴포넌트의 this 바인딩
import { Component } from "react";
class EventPractice extends Component {
state = {
message: "",
};
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({ message: e.target.value });
}
handleClick(e) {
alert(this.state.message);
this.setState({ message: "" });
}
render() {
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나입력하세요"
onChange={this.handleChange}
value={this.state.message}
></input>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
import { Component } from "react";
class EventPractice extends Component {
state = {
message: "",
};
handleChange(e) {
this.setState({ message: e.target.value });
console.log(this.state);
}
handleClick() {
alert(this.state.message);
this.setState({ message: "" });
}
render() {
return (
...
placeholder="아무거나입력하세요"
onChange={this.handleChange.bind(this)}
value={this.state.message}
></input>
<button onClick={this.handleClick.bind(this)}>확인</button>
</div>
);
}
}
export default EventPractice;
아니면 호출되는 콜백함수 자체에 this를 바인딩 해줘도 됩니다.
그런데 우리는 알아야 할게 있습니다. 화살표 함수의 this는 바로 상위 스코프를 가르키게 되졍?
import { Component } from "react";
class EventPractice extends Component {
state = {
message: "",
};
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="아무거나입력하세요"
onChange={this.handleChange}
value={this.state.message}
></input>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
따라서 콜백함수의 상위 스코프에서는 this가 state(즉 인스턴스)를 가리키고 잇으니까!! 가능허다~
바로 화살표 함수로 해결될 일.. 이었으빈다.. 충격적이져? ㅜ constructor 내부에서 this 바인딩을 하지 않아도, 화살표 함수로 메서드를 정의해주면 된다..!!!! 예아~
않의 생각해보니, input이 5천개면 어떡하죠? 각각 인풋에 맞춰서 함수를 만들어줘야할까요? 그러고 싶진 않네요.. 효율적인 방법이 없을까요?
⚬ input 여러개 다루기
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(e.target.name);
};
[e.target.name]으로 key값을 설정해주면 됩니다!! 매우 핵심적이 내용이죠
⚬ 함수형 컴포넌트 실습
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"
value={username}
placeholder="사용자명"
onChange={onChangeUsername}
/>
<input
type="text"
name="message"
value={message}
placeholder="사용자명"
onChange={onChangeMessage}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
);
};
export default EventPractice;
하지만 input이 개마나진다면~~~??
import React, { useState } from "react";
const EventPractice = () => {
const [form, setForm] = useState({
username: "",
message: "",
});
const { username, message } = form;
const onChange = (e) => {
setTimeout(() => console.log(e), 500);
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;