리액트의 이벤트 시스템은 웹 브라우저의 HTML 이벤트와 인터페이스가 동일하기 때문에 사용법이 많이 비슷하다.
HTML의 onclick은 리액트에서 onClick
으로 작성한다. onkeyup은 onKeyUp
이다.
화살표 함수를 이용해서 바로 만들어서 전달해도 되고, 렌더링 부분 외부에서 만들어서 전달해도 된다.
div
, input
등의 DOM 요소에는 이벤트를 설정할 수 있지만 사용자가 직접 만든 <MyComponent />
, <MyButton />
등과 같은 컴포넌트에는 이벤트를 설정할 수 없다.
하지만 전달받은 props를 컴포넌트 내부의 DOM 이벤트로 설정할 수는 있다.
<div onClick={this.props.onClick}></div>
이런 식으로...
export default function Event() {
return (
<div>
<h1>Event</h1>
<input
type="text"
name="message"
onChange={(e) => {
console.log(e);
}}
/>
</div>
);
}
값이 변할 때마다 콘솔에 이벤트가 출력되고 있는 것을 확인할 수 있다.
여기서 콘솔에 기록되는 e 객체는 SyntheticEvent
로, 웹 브라우저의 네이티브 이벤트를 감싸는 객체이다.
입력한 input 값을 알고 싶다면 e.target.value
를 출력해보면 된다.
state와 이벤트를 연계할 수도 있다. 다음 코드를 보자.
export default function Event() {
const [comment, setComment] = useState("안녕하세요");
return (
<div>
<h1>comment : {comment}</h1>
<button onClick={() => {
setComment("");
}}>
click!
</button>
</div>
);
}
버튼을 클릭하면 setComment 함수가 호출되어 comment가 공백이 되는 것을 볼 수 있다.
화살표 함수로 바로 전달하여 만드는 방법 외에도, 외부에서 별도의 함수를 만들어 전달하는 방법도 물론 가능하다.
export default class Event 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() {
this.setState({ message: "" });
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
<input type="text" value={this.state.message} onChange={this.handleChange} />
<button onClick={this.handleClick}>Clear</button>
</div>
);
}
}
위의 코드를 바벨의 transform-class-properties 문법을 이용해 화살표 함수 형태의 메서드를 정의하여 개선하면 다음과 같다.
export default class Event extends Component {
state = {
message: "",
};
handleChange = (e) => {
this.setState({
message: e.target.value
});
}
handleClick = (e) => {
alert(this.state.message);
this.setState({
message:''
});
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
<input type="text" value={this.state.message} onChange={this.handleChange} />
<button onClick={this.handleClick}>Clear</button>
</div>
);
}
}
input이 여러 개일 때는 메서드를 여러 개 만들 수도 있지만, 더 쉽게 처리할 수 있는 방법이 있다.
event 객체를 활용하는 방법이 그것이다. e.target.name
을 활용하면, 해당 인풋의 name을 가리키게 되므로, input 태그의 name 속성에 state 변수를 지정해 주면 쉽게 값을 설정할 수 있다.
export default class Event extends Component {
state = {
message: "",
name: "",
};
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
});
}
handleClick = (e) => {
alert(this.state.name + ":" + this.state.message);
this.setState({
message:'',
name:''
});
}
render() {
return (
<div>
<h1>{this.state.message}</h1>
<input type="text" value={this.state.name} name="name" onChange={this.handleChange} placeholder="name"/>
<input type="text" value={this.state.message} name="message" onChange={this.handleChange} placeholder="message"/>
<button onClick={this.handleClick}>Clear</button>
</div>
);
}
}
객체 안에서 key를 대괄호 []
로 감싸면, 그 안에 넣은 레퍼런스가 가리키는 실제 값이 key 값으로 사용된다.
function Event() {
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("");
}
return (
<div>
<h1>{username} {message}</h1>
<input type="text" name="message" value={username} placeholder="username" onChange={onChangeUsername}/>
<input type="text" name="username" value={message} placeholder="message" onChange={onChangeMessage}/>
<button onClick={onClick}>O</button>
</div>
)
}