이벤트 : 웹 페이지에서 일어나는 사용자의 행위이다.
ex) 버튼 클릭, 페이지 스크롤, 새로고침 등
이벤트 핸들링 : 이벤트가 발생하면 특정 코드가 동작하도록 만드는 작업이다.
ex) 버튼을 클릭했을 때 경고 대화상자를 브라우저에 표시
function Body() {
function handleOnClick() {
alert("버튼을 클릭하셨군요!");
}
return (
<div className="body">
<button onClick={handleOnClick}>클릭하세요</button>
</div>
);
}
export default Body;
이벤트가 발생하면 이벤트 핸들러에게 이벤트 객체를 매개변수로 전달한다.
function Body() {
function handleOnClick(e) {
console.log(e.target.name);
}
return (
<div className="body">
<button name="A버튼" onClick={handleOnClick}>
A 버튼
</button>
<button name="B버튼" onClick={handleOnClick}>
B 버튼
</button>
</div>
);
}
export default Body;
function handleOnClick(e) {
console.log(e);
console.log(e.target.name);
}
State는 상태라는 뜻이다.
리액트 컴포넌트 또한 State 값에 따라 다른 결과를 렌더링 한다.
useState의 용법
const [light, setLight] = useState('off');
State 변수 set 함수 생성자(초깃값)
import { useState } from "react";
function Body() {
const [count, setCount] = useState(0);
const onIncrease = () => {
setCount(count + 1);
};
return (
<div>
<h2>{count}</h2>
<button onClick={onIncrease}>+</button>
</div>
);
}
export default Body;
텍스트, 전화번호, 날짜, 체크박스 등
import { useState } from "react";
function Body() {
const handleOnChange = (e) => {
console.log(e.target.value);
};
return (
<div>
<input onChange={handleOnChange} />
</div>
);
}
export default Body;
-> 현재 텍스트가 리액트 컴포넌트가 관리하는 State에 저장되어 있지는 않다.
import { useState } from "react";
function Body() {
const [text, setText] = useState("");
const handleOnChange = (e) => {
setText(e.target.value);
};
return (
<div>
<input value={text} onChange={handleOnChange} />
<div>{text}</div>
</div>
);
}
export default Body;
import { useState } from "react";
function Body() {
const [date, setDate] = useState("");
const handleOnChange = (e) => {
console.log("변경된 값: ", e.target.value);
setDate(e.target.value);
};
return (
<div>
<input type="date" value={date} onChange={handleOnChange} />
</div>
);
}
export default Body;
<select> 태그와 <option> 태그가 함께 사용한다.
import { useState } from "react";
function Body() {
const [option, setOption] = useState("");
const handleOnChange = (e) => {
console.log("변경된 값: ", e.target.value);
setOption(e.target.value);
};
return (
<div>
<select value={option} onChange={handleOnChange}>
<option key={"1번"}>1번</option>
<option key={"2번"}>2번</option>
<option key={"3번"}>3번</option>
</select>
</div>
);
}
export default Body;
여러 줄의 텍스트를 입력할 때 <textarea> 태그를 사용한다.
import { useState } from "react";
function Body() {
const [text, setText] = useState("");
const handleOnChange = (e) => {
console.log("변경된 값 : ", e.target.value);
setText(e.target.value);
};
return (
<div>
<textarea value={text} onChange={handleOnChange} />
</div>
);
}
export default Body;
import { useState } from "react";
function Body() {
const [name, setName] = useState("");
const [gender, setGender] = useState("");
const [birth, setBirth] = useState("");
const [bio, setBio] = useState("");
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeGender = (e) => {
setGender(e.target.value);
};
const onChangeBirth = (e) => {
setBirth(e.target.value);
};
const onChangeBio = (e) => {
setBio(e.target.value);
};
return (
<div>
<div>
<input value={name} onChange={onChangeName} placeholder="이름" /> ①
</div>
<div>
<select value={gender} onChange={onChangeGender}> ②
<option key={""}></option>
<option key={"남성"}>남성</option>
<option key={"여성"}>여성</option>
</select>
</div>
<div>
<input type="date" value={birth} onChange={onChangeBirth} /> ③
</div>
<div>
<textarea value={bio} onChange={onChangeBio} /> ④
</div>
</div>
);
}
export default Body;
-> 객체 자료형을 이용해 간결하게 코드를 작성할 수 있다.
import { useState } from "react";
function Body() {
const [state, setState] = useState({ ①
name: "",
gender: "",
birth: "",
bio: "",
});
const handleOnChange = (e) => {
console.log("현재 수정 대상:", e.target.name);
console.log("수정값:", e.target.value);
setState({
...state,
[e.target.name]: e.target.value,
});
};
return (
<div>
<div>
<input
name="name" ②
value={state.name} ③
onChange={handleOnChange} ④
placeholder="이름"
/>
</div>
<div>
<select name="gender" value={state.gender} onChange={handleOnChange}>
<option key={""}></option>
<option key={"남성"}>남성</option>
<option key={"여성"}>여성</option>
</select>
</div>
<div>
<input
name="birth"
type="date"
value={state.birth}
onChange={handleOnChange}
/>
</div>
<div>
<textarea name="bio" value={state.bio} onChange={handleOnChange} />
</div>
</div>
);
}
export default Body;
① 객체 자료형으로 State를 하나 생성하고 초깃값을 설정한다. State 변수인 객체 state의 초깃 값은 모두 공백 문자열("")이며, name, gender, birth, bio 프로퍼티가 있다.
② 모든 입력 폼에서 name 속성을 지정한다.
③ 모든 입력 폼의 value를 객체 state의 프로퍼티 중 하나로 설정한다.
④ 사용자의 입력을 처리할 이벤트 핸들러 handleOnChange를 생성한다.
State를 Props로 전달할 수 있다.
import "./Body.css";
import { useState } from "react";
function Viewer({ number }) {
return <div>{number % 2 === 0 ? <h3>짝수</h3> : <h3>홀수</h3>}</div>;
}
function Body() {
const [number, setNumber] = useState(0);
const onIncrease = () => {
setNumber(number + 1);
};
const onDecrease = () => {
setNumber(number - 1);
};
return (
<div>
<h2>{number}</h2>
<Viewer number={number} />
<div>
<button onClick={onDecrease}>-</button>
<button onClick={onIncrease}>+</button>
</div>
</div>
);
}
export default Body;
부모에 속해 있는 State(number) 값이 변하면 Viewer 컴포넌트에서 구현한 ‘짝수’, ‘홀수’ 값도 따라서 변한다.
->자식 컴포넌트는 Props로 전달된 State 값이 변하면 자신도 리렌더 된다는 것을 알 수 있다.
다음은 부모 컴포넌트가 자식에게 State를 Props로 전달하지 않는 경우이다.
import { useState } from "react";
function Viewer() {
console.log("viewer component update!");
return <div>Viewer</div>;
}
function Body() {
const [number, setNumber] = useState(0);
const onIncrease = () => {
setNumber(number + 1);
};
const onDecrease = () => {
setNumber(number - 1);
};
return (
<div>
<h2>{number}</h2>
<Viewer />
<div>
<button onClick={onDecrease}>-</button>
<button onClick={onIncrease}>+</button>
</div>
</div>
);
}
export default Body;
콘솔에서 6번의 viewer component update! 가 출력된다.
-> 리액트에서는 부모 컴포넌트가 리렌더 하면 자식도 함께 리렌더 된다는 것을 알 수 있다.
돔(DOM) 요소들을 직접 조작할 수 있다.
Reference의 줄임말로 참조를 뜻한다.
useRef라는 리액트 함수를 이용해 Ref 객체를 생성한다.
import { useRef, useState } from "react";
function Body() {
const [text, setText] = useState("");
const textRef = useRef();
const handleOnChange = (e) => {
setText(e.target.value);
};
const handleOnClick = () => {
alert(text);
};
return (
<div>
<input ref={textRef} value={text} onChange={handleOnChange} />
<button onClick={handleOnClick}>작성 완료</button>
</div>
);
}
export default Body;
-> 입력 폼에 대한 어떤 조작도 아직 시도하지 않았기 때문에 아직 아무런 변화가 없다.
import { useRef, useState } from "react";
function Body() {
(...)
const handleOnClick = () => {
alert(text);
textRef.current.value = "";
};
(...)
}
export default Body;
사용자가 특정 폼에 내용을 입력하지 않거나 내용이 정한 길이보다 짧으면 해당 폼을 포커스(focus)하여 사용자의 추가 입력을 유도한다.
import { useRef, useState } from "react";
function Body() {
const [text, setText] = useState("");
const textRef = useRef();
const handleOnChange = (e) => {
setText(e.target.value);
};
const handleOnClick = () => {
if (text.length < 5) {
textRef.current.focus(); ①
} else {
alert(text);
setText(""); ②
}
};
return (
<div>
<input ref={textRef} value={text} onChange={handleOnChange} />
<button onClick={handleOnClick}>작성 완료</button>
</div>
);
}
export default Body;
① <input> 태그로 지정한 폼에 입력한 텍스트가 다섯 글자보다 적다면 textRef.current가 참조하는 입력 폼에 포커스를 실행한다. focus()는 현재 돔 요소에 포커스를 지정하는 메서드이다.
② 텍스트 폼에 입력한 값을 초기화하기 위해 set 함수 setText를 호출하고 인수로 빈 문자열을 전달한다. Ref를 사용하지 않고도 set 함수로 입력 폼을 초기화할 수 있다.
리액트 컴포넌트에서 클래스로 만든 리액트 컴포넌트의 기능을 이용하도록 도와주는 함수들이다.
이름이 use로 시작한다.
State를 만드는 함수 useState와 참조 객체를 만드는 함수 useRef가 훅에 해당한다.
이론문제
1. 이벤트가 발생하면 특정 코드가 동작하도록 만드는 작업을 ( )라고 한다.
2. 이벤트 핸들러를 설정할 때는 함수 호출의 결괏값을 전달하는 것이 아니라 ( )를 전달한다.
3. State 값이 변해 컴포넌트를 다시 렌더링 하는 것을 ( ) 또는 ( )이라 한다.
4. 드롭다운 상자로 여러 옵션 중에 하나 선택하려면 ( ) 태그와 ( ) 태그를 함께 사용한다.
5. 글상자로 여러 줄의 텍스트 입력하려면 ( ) 태그를 사용한다.
6. ( )라는 리액트 함수를 이용해 Ref 객체를 생성한다.
7. 리액트 훅은 이름이 ( )로 시작한다.
실습문제
1. <textarea> 태그를 사용하여 글상자로 여러 줄의 텍스트 입력하는 코드를 짜보아라.
2. <input> 태그로 지정한 폼에 입력한 텍스트가 열 글자보다 적다면 포커스를 실행하는 코드를 작성해라.
이론문제 답 : 이벤트 핸들링 / 함수 그 자체 / 리렌더, 리렌더링 / select, option / textarea / useRef / use
실습문제 1번 답
import { useState } from "react";
function Body() {
const [text, setText] = useState("");
const handleOnChange = (e) => {
console.log("변경된 값 : ", e.target.value);
setText(e.target.value);
};
return (
<div>
<textarea value={text} onChange={handleOnChange} />
</div>
);
}
export default Body;
실습문제 2번 답
import { useRef, useState } from "react";
function Body() {
const [text, setText] = useState("");
const textRef = useRef();
const handleOnChange = (e) => {
setText(e.target.value);
};
const handleOnClick = () => {
if (text.length < 10) {
textRef.current.focus();
} else {
alert(text);
setText("");
}
};
return (
<div>
<input ref={textRef} value={text} onChange={handleOnChange} />
<button onClick={handleOnClick}>작성 완료</button>
</div>
);
}
export default Body;
출처: 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023), 5-4 ~ 5-6장.
Editor: yunseul
[리액터 스타터2] Hooks (1) | 2023.11.24 |
---|---|
[리액트 스타터2] project 1 [카운터] 앱 만들기 ~ 6장. 라이프 사이클과 리액트 개발자 도구 (0) | 2023.11.17 |
[리액트 스타터2] 5장. 리액트의 기본 기능 다루기(1) (1) | 2023.11.03 |
[리액트 스타터2] 4장. 리액트 시작하기 (0) | 2023.10.13 |
[리액트 스타터2] 3장. Node.js (0) | 2023.10.13 |