5-1 이벤트 연결하기
JSX에서 함수 연결하기
## 리액트의 컴포넌트는 상태를 가지고 그 상태의 변화에 따라서 컴포넌트가 리렌더링 된다.
그 말은 리엑트 컴포넌트의 상태에 변화를 주는 무언가가 있다는 것
그 무언가의 대부분이 대부분 이벤트 이다.
JSX에서 camelCase 형태의 속성에 함수를 전달
<button onClick={handleClick}>
Button
</button>
아래 예시 이미지처럼 리액트에서 이벤트를 바인딩을 하게 되면, 해당하는 이벤트가 발생이 됐을 때 해당 함수에 클릭에 대한 이벤트 객체를 넘겨주게 된다. 함수에서는 인자로 받는다.
아래는 리엑트로 이벤트 등록하는 것이 아닌, 자바스크립트로 이벤트 등록하는 스크립트
document.body.addEventListener('click', (e) => {console.log(e)});
자바스크립트에서 전달해주는 이벤트를 진짜 이벤트 객체라고 한다면, 리엑트에서 연결하고 받게 되는 이벤트 객체는 합성 이벤트라고 해서 진짜 이벤트 객체를 원본으로 해서 확장한 이벤트 객체이다.
추가정보
/**
* ℹ️합성 이벤트 (SyntheticEvent)
* - React에서 이벤트가 발생할 때, 이벤트 핸들러의 인자로 합성 이벤트 객체가 전달됨
* - 이 합성 이벤트는 javascript 에서 전달 받는 이벤트 객체를 확장(래핑)한 객체임
* (거의 동일한 인터페이스를 가지고 있음)
* - 원본 이벤트 객체(native event)는 syntheticEvent.nativeEvent 에 있음
* - 지금은 그냥 같은 이벤트 객체라고 생각해도 무방
*/
/**
* ℹ️이벤트 핸들러(함수)를 만들 때는 react lifecycle을 고려하자!
* - 컴포넌트가 리랜더링 되면 컴포넌트 내에서 단순 정의한 함수가 새로운 함수로 만들어짐
* - 이것은 불필요한 작업으로 성능 문제를 야기함
* - 그래서 함수의 정의를 최대한 컴포넌트 밖으로 빼거나,
* useCallback으로 감싸줘서 매 랜더링 마다 새로 만들어지지 않도록 해줄 필요가 있음
*/
5-2 이벤트 종류
function App() {
return (
<div className="App">
<button
onClick={() => {
console.log("onClick");
}}
onMouseDown={() => {
console.log("onMouseDown");
}}
onMouseUp={() => {
console.log("onMouseUp");
}}
>
Button
</button>
<div
className="box"
onClick={() => {
console.log("onClick");
}}
onMouseEnter={() => {
console.log("onMouseEnter");
}}
onMouseLeave={() => {
console.log("onMouseLeave");
}}
onMouseMove={() => {
console.log("onMouseMove");
}}
></div>
<div>
<input
type="text"
onKeyDown={() => {
console.log("onKeyDown");
}}
onKeyUp={() => {
console.log("onKeyUp");
}}
onKeyPress={() => {
console.log("onKeyPress");
}}
onFocus={() => {
console.log("onFocus");
}}
onBlur={() => {
console.log("onBlur");
}}
onChange={() => {
console.log("onChange");
}}
/>
</div>
</div>
);
}
export default App;
5-3 Form
Controlled Component (제어 컴포넌트) 라는 개념
React에 의해 입력 요소의 값이 제어되는 컴포넌트
장점
- 컴포넌트의 state와 input value가 완전히 동일한 값을 갖음
- 다른 컴포넌트에 input value를 전달하거나 다른 이벤트 핸들러에서 값을 재설정 할 수 있음
단점
- 값이 변경되는 매 순간 렌더링이 된다. (해당 컴포넌트의 영향 범위가 클 수록 성능 저하)
5-4 설문조사 만들기
App.js
import { useState } from "react";
import TextInput from "./components/TextInput";
import Select from "./components/Select";
const contryOptions = ["한국", "중국", "일본", "러시아", "미국"];
function App() {
const [formValue, setFormValue] = useState({
name: "",
contry: "",
address: "",
});
console.log("[App]", formValue);
return (
<div className="App">
<div className="form">
<div className="form-item">
<h1>1. 이름이 무엇인가요?</h1>
<TextInput
value={formValue.name}
setValue={(value) => {
setFormValue((state) => ({
...state,
name: value,
}));
}}
/>
</div>
<div className="form-item">
<h1>2. 사는 곳은 어딘가요?</h1>
<Select
value={formValue.contry}
setValue={(value) => {
setFormValue((state) => ({
...state,
contry: value,
}));
}}
options={contryOptions}
/>
</div>
{formValue.contry === "한국" ? (
<div className="form-item">
<h1>2-1. 한국 어디에 사나요?</h1>
<TextInput
value={formValue.address}
setValue={(value) => {
setFormValue((state) => ({
...state,
address: value,
}));
}}
/>
</div>
) : null}
<div className="button-group">
<button
onClick={() => {
alert("저장되었습니다.");
setFormValue({
name: "",
contry: "",
address: "",
});
}}
disabled={formValue.name === "" || formValue.contry === ""}
>
저장
</button>
</div>
</div>
</div>
);
}
export default App;
Select.js
import { useState } from "react";
function Select({ value, setValue, options = [] }) {
return (
<select
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
>
<option value="" disabled>
지역을 선택해주세요.
</option>
{options.map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</select>
);
}
export default Select;
TextInput.js
import { useState } from "react";
function TextInput({ value, setValue }) {
return (
<input
type="text"
value={value}
onChange={(e) => {
setValue(e.target.value);
}}
/>
);
}
export default TextInput;
'리엑트 > 실무 중심 FE 입문자를 위한 React' 카테고리의 다른 글
07 React 메모장 만들기 (0) | 2024.08.16 |
---|---|
06 React 환경 설정 (0) | 2024.08.15 |
04 LifeCycle과 Hooks (0) | 2024.08.13 |
Chapter 03 컴포넌트 (0) | 2024.06.13 |
JSX (0) | 2024.06.10 |
댓글