리액트를 다루는 기술 - 김민준
4. 이벤트 핸들링
DOM의 Event (문자열로 전달)
<button onclick="activate()">
Activate
</button>
리액트의 Event (함수 그대로를 전달)
<button onClick={activate}>
Activate
</button>
<용어정리>
이벤트 : 사용자가 웹 브라우저에서 DOM 요소들과 상호작용 하는 것
이벤트 핸들러란? 이벤트가 발생하면 처리하는 역할
이벤트 사용시 주의사항
1. 카멜표기법
2. 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값(객체 자체)을 전달해야한다.
3. DOM 요소에만 이벤트를 설정할 수 있음 : 즉, 우리가 만든 컴포넌트에는 이벤트를 설정할 수 없고 DOM 요소인 div, button, span, form등에만 설정할 수 있다. 우리가 만든 컴포넌트에 onClick = {clickHandler} 을 설정한다면 단지 onClick이라는 이름의 prop을 전달하는 것으로 간주한다.
<input
type="text"
name="message"
placeholder="text me"
onChange={(e) => {
console.log(e)
}}
/>
인풋 태그 내 onChange 이벤트핸들러를 작성하고 텍스트를 입력하면 e 객체가 콘솔에 찍히는데, SyntheticEvent라고 한다. (합성이벤트)
이는 모든 브라우저에서 이벤트를 동일하게 처리하기 위한 이벤트 래퍼이다. 브라우저 종류마다 다른 고유이벤트는 nativeEvent 라고 한다. 리액트는 네이티브 이벤트와 동일한 인터페이스를 가지면서 이 합성 이벤트를 정의하기 때문에 브라우저 호환성을 걱정하지 않아도 된다(크로스 브라우징).
https://ko.legacy.reactjs.org/docs/events.html
4.2.3 버튼을 누르면 input 값을 띄우고 공백으로 클리어
import { useState } from "react"
const EventPractice = () => {
const [state,setState] = useState('')
const clickHandler = (e) => {
alert(state)
setState('') //공백으로 초기화
}
const changeHandler = (e) => {
setState(e.target.value)
}
return (
<div className="eventPractice">
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="text me"
value = {state}
onChange={changeHandler}
/>
<button onClick={clickHandler}>
확인
</button>
</div>
)
}
export default EventPractice
4.2.4 여러개의 인풋으로 state를 저장하려면 e.target.name 으로 함수를 하나만 만들어서 재사용할 수 있음
원래 책에는 class형으로 나와있는데 함수형이 더 익숙해서 함수형으로 바꿔보았다. 근데 인풋 두개 중 마지막 하나만 state에 담겨서 계속 고민했다. 알고보니 setState 을 할 때 스프레드 연산으로 복사해야 했는데 그걸 안해서 문제였다.
스프레드연산을 하지 않는다면 배열의 복사가 이루어지는 것이 아니라 같은 참조값을 가지게 되어 원본도 같이 수정되는 문제가 생긴다.
setState({...state, [e.target.name]: e.target.value})
이렇게 스프레드 연산을 통해 새로운 참조값을 가진 오브젝트를 새로 만들어줘야한다. 그 오브젝트가 변경된 내용물을 가지게 되고 불변성을 유지한다.
그러나 spread operator은 값을 복사할 때 얕은 복사를 하게 되므로 가장 바깥쪽에 있는 값만 복사된다. 객체 안의 변수에 또 객체가 담겨있다면 그 내부의 값도 또한 복사해주어야 한다. 이때는 immer 라이브러리를 통해 불변성을 관리해주면 된다.
(근데 책을 3장 넘기니까 함수형코드가 나와있었음 ㅎㅎ^^)
import { useState } from "react"
const EventPractice = () => {
const [state,setState] = useState({
username: '',
message: '',
})
const handleChange = (e) => {
setState({...state, [e.target.name] : e.target.value})
console.log(state)
}
const handleClick = () => {
console.log(state)
alert(state.username, state.message)
setState({
username: '',
message: '',
})
}
return (
<div className="eventPractice">
<h1>이벤트 연습</h1>
<input
type="text"
name="username"
placeholder="user name"
value = {state.username}
onChange={handleChange}
/>
<input
type="text"
name="message"
placeholder="message"
value = {state.message}
onChange={handleChange}
/>
<button onClick={handleClick}>
확인
</button>
</div>
)
}
export default EventPractice
+추가: 객체에서 key 값 접근하기
setState({...state, [e.target.name] : e.target.value})
- handleKeyPress()
const handleKeyPress = (e) => {
e.key === "Enter" && handleClick()
}
조건문을 사용해 enter 키 일 경우 click() 핸들러와 같은 함수를 실행시킴 => ux 향상
'Computer Programming > [리액트를 다루는 기술]' 카테고리의 다른 글
[리액트를 다루는 기술] 11. 컴포넌트 성능 최적화 (1) | 2023.06.19 |
---|---|
[리액트를 다루는 기술] 10. Todo List 만들기 (2) | 2023.06.17 |
[리액트를 다루는 기술] 9. 컴포넌트 스타일링 (0) | 2023.06.16 |
[리액트를 다루는 기술] 8. Hooks | Custom Hooks (0) | 2023.06.16 |
[리액트를 다루는 기술] 6. 컴포넌트의 반복 (map, key, 데이터 추가 및 삭제, concat, filter) (0) | 2023.06.15 |