티스토리 뷰
리액트의 이벤트 시스템은 웹 브라우저의 HTML 이벤트와 인터페이스가 동일하기 때문에 사용법이 꽤나 비슷하다.
리액트에서 이벤트를 사용할 때 주의할 사항들이 몇 가지가 존재하는데, 이는 다음과 같다.
1. 이벤트 이름은 Camel Case: 예를 들어 HTML의 onclick은 onClick으로 작성해야 한다.
2. 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달한다.
3. DOM 요소에만 이벤트를 설정할 수 있다. 직접 만든 컴포넌트에는 자체적으로 이벤트를 설정할 수 없다.
바로 한번 예제와 함께 알아보도록 하자.
우선, 예제로 사용할 컴포넌트를 생성하여 불러오자.
◎EventPractice.js
import {Component} from 'react';
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
</div>
);
}
}
export default EventPractice;
◎App.js
import EventPractice from "./EventPractice";
const App = () => {
return <EventPractice/>
};
export default App;
이제 input 태그를 렌더링하는 코드와 해당 태그에 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);
}
}
/>
</div>
);
}
}
export default EventPractice;
사실 별 건 없다. element 내부에 이벤트를 선언해주고, 그 안에 호출할 함수를 작성해주면 된다.
이제 state에 input 태그의 값을 보내보자. 캡처하기가 좀 불편해서 부모 태그에 margin도 추가했다.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<h2>입력 값: {this.state.message}</h2>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
(e) => {
this.setState({
message: e.target.value
})
}
}
/>
</div>
);
}
}
export default EventPractice;
간단하게 버튼 하나만 더 추가해보자.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<h2>입력 값: {this.state.message}</h2>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
(e) => {
this.setState({
message: e.target.value
})
}
}
/>
<button onClick={() => {
alert(this.state.message);
this.setState({
message: ''
})
}}>확인</button>
</div>
);
}
}
export default EventPractice;
임의 메서드 만들기
별 다른 내용이 있는 건 아니고, 이벤트 선언 부에서 바로 작성하는 게 아니라 미리 선언해놓은 메서드 또한 사용이 가능하다는 내용이다.
코드는 아래와 같이 작성할 수 있다.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleChange(e) {
this.setState({
message: e.target.value
})
}
handleClick(e) {
alert(this.state.message);
this.setState({
message: ''
})
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<h2>입력 값: {this.state.message}</h2>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
this.handleChange
}
/>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
주의할 점은 미리 생성해놓은 메서드를 이벤트로 등록하기 위해서는 생성자에서 해당 메서드를 컴포넌트 자체(this)와 Bind 하는 작업이 필요하다. 그렇지 않으면 함수가 호출될 때 this는 호출부에 따라 결정되기 때문에 클래스의 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어진다.
바인딩이 되지 않는 경우라면, 각 메서드가 보고 있는 this가 undefined를 가리키게 된다.
메서드 바인딩은 생성자 메서드에서 하는 것이 정석이지만, 이 작업이 다소 번거롭다고 느껴질 수도 있다.
새 메서드를 만들 때마다 constructor도 수정해야 하기 때문인데, 이 작업을 좀 더 간단하게 하는 방법이 있다.
바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메서드를 정의하면 된다.
화살표 형태로 함수를 지정하면, 보고 있는 this가 부모 컴포넌트로 고정되기 때문에 문제 없이 동작한다.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
handleChange = (e) =>{
this.setState({
message: e.target.value
})
}
handleClick = (e) =>{
alert(this.state.message);
this.setState({
message: ''
})
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<h2>입력 값: {this.state.message}</h2>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
this.handleChange
}
/>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
input 여러 개 다루기
input 태그가 여러 개이고, state 또한 여러 개를 다뤄야 한다면 아래와 같이 state 객체의 키 값과 input 요소의 이름을 맞춰준 뒤에 event 객체를 활용하여 이를 구분할 수 있다.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: '',
username: ''
}
handleChange = (e) =>{
this.setState({
[e.target.name]: e.target.value
});
}
handleClick = (e) =>{
alert(this.state.username + ': ' + this.state.message);
this.setState({
message: ''
})
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<input
type="text"
name="username"
placeholder="사용자명"
value={this.state.username}
onChange={
this.handleChange
}
/>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
this.handleChange
}
/>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
handleChange = (e) =>{
this.setState({
[e.target.name]: e.target.value
});
}
와 같이 객체 안에서 key를 []로 감싸면 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key 값으로 사용된다.
onKeyPress 이벤트도 추가해보자.
import {Component} from 'react';
class EventPractice extends Component {
state = {
message: '',
username: ''
}
handleChange = (e) =>{
this.setState({
[e.target.name]: e.target.value
});
}
handleClick = (e) =>{
alert(this.state.username + ': ' + this.state.message);
this.setState({
message: ''
})
}
handleKeyPress = (e) => {
if(e.key === 'Enter') {
this.handleClick(e);
}
}
render() {
return (
<div style={{margin: 20}}>
<h1>이벤트 연습</h1>
<input
type="text"
name="username"
placeholder="사용자명"
value={this.state.username}
onChange={
this.handleChange
}
/>
<input
type="text"
name="message"
placeholder="입력해주세요."
value={this.state.message}
onChange={
this.handleChange
}
onKeyPress={this.handleKeyPress}
/>
<button onClick={this.handleClick}>확인</button>
</div>
);
}
}
export default EventPractice;
함수 컴포넌트로 바꿔보기
위 예제 코드를 함수형 컴포넌트로 변경해보자.
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"
placeholder="사용자명"
value={username}
onChange={onChangeUsername}
/>
<input
type="text"
name="message"
placeholder="아무거나 입력해보세요."
value={message}
onChange={onChangeMessage}
onKeyPress={onKeyPress}
/>
<button onClick={onClick}>확인</button>
</div>
)
}
input이 2개 뿐이라면 위 코드도 괜찮지만, input의 개수가 많아진다면 e.target.name을 활용하는 것이 훨씬 좋다.
또한 useState를 통해 사용하는 상태에 문자열이 아닌 객체를 넣어보자.
import {useState} from 'react'
const EventPractice = () => {
const [form, setForm] = useState({
username: '',
message: ''
});
const {username, message} = form;
const onChange = e => {
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
끝!
'WEB > React' 카테고리의 다른 글
[React] 컴포넌트 반복 (0) | 2023.03.24 |
---|---|
[React] ref: DOM에 이름 달기 (0) | 2023.03.24 |
[React] Component (0) | 2023.03.23 |
[React] JSX 문법 (0) | 2023.03.23 |
[React] Hello, React! (0) | 2023.03.22 |
- redux-thunk
- Async
- react
- 이탈리안 레스토랑
- 인천 구월동 맛집
- redux
- Promise
- javascript
- 파니노구스토
- AsyncStorage
- 인천 구월동 이탈리안 맛집
- 맛집
- react-native
- 정보보안기사 #실기 #정리
- await
- Total
- Today
- Yesterday