1. 일반 변수 선언 (화면 렌더링에 영향 없음)
2. 상태 변수 선언 (화면 렌더링에 영향 있음)
React에서 상태를 사용해 폼 요소나 화면 UI를 제어 컨트롤러 방식으로 관리 가능
실시간으로 제어하는 방식임기본 문법
// 비구조화할당
const [state, setState] = useState(초기값);
state: 현재 상태 값setState: 상태 값을 변경하는 함수초기값: 상태의 초기값import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1); //값 전달 시 count의 최신값으로 설정
};
return (
<div>
<h1>count: {count}</h1>
<button onClick={increment}>증가</button>
</div>
);
}
✅ 관례
- 상태 이름이
count면 업데이트 함수는setCount로 작명- 예:
isVisible→setIsVisible,userName→setUserName
setCount(count + 1); //값 전달 시 count의 최신값으로 설정
setState((현재상태) ⇒ 값)setCount((count) => count + 1); //콜백함수 반환값이 count의 최신값으로 설정
이전 상태를 참조해야 할 때 사용값 전달 방식과 콜백 함수 방식의 주요 차이점은 상태 업데이트의 동작 방식에 있음
예시: 3번의 상태 업데이트 시도
const increment = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
count는 1만 증가함. 각 setCount가 동일한 count 값을 참조하기 때문(비동기)
하지만 콜백 함수 사용 시:
const increment = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
};
count가 3씩 증가함. 각 콜백이 이전 상태의 최신값을 참조하여 업데이트하기 때문
React는 불변성을 기반으로 상태 변화를 감지
✅ 즉, 상태를 직접 변경하지 않고 새로운 상태를 생성해야 함
const [students, setStudents] = useState(["james", "john"]);
const addStudent = () => {
// ❌ 잘못된 방식 (원본 수정)
// students.push("smith");
// setStudents(students);
// ✅ 올바른 방식 (새 배열 생성)
setStudents((prevStudents) => [...prevStudents, "smith"]);
};
💡 올바른 방식: spread 연산자(...), map(), filter()를 사용해 새로운 상태를 생성
interface User {
name: string;
age: number;
gender?: string; // 선택적(optional) 속성
}
const [user, setUser] = useState<User>({ name: "john", age: 20 });
// gender는 선택적 속성으로 추가 가능
const updateUser = () => {
setUser(prev => ({ ...prev, gender: "male" }));
};
const [input, setInput] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInput(e.target.value);
};
return <input type="text" value={input} onChange={handleChange} />;
// 혹은 onChange 내에서 직접 호출
<input type="text" value={input} onChange={(e) => setInput(e.target.value)} />
💡
value와onChange는 폼 요소 제어 시 세트로 사용
- value 속성 없으면 리셋 기능 추가해도 인풋 내부 값 제어 불가
- 폼 요소 완전 제어를 위해 value와 onChange 함께 사용 필수
// date input
const [dateInput, setDateInput] = useState("");
<input type="date" value={dateInput} onChange={(e) => setDateInput(e.target.value)} />
// textarea
const [textInput, setTextInput] = useState("초기값");
<textarea value={textInput} onChange={(e) => setTextInput(e.target.value)} />
const [checked, setChecked] = useState(false);
<input type="checkbox" checked={checked} onChange={() => setChecked(!checked)} />;
초기값 설정 필수 ⇒ defaultChecked 설정
const [radioValue, setRadioValue] = useState("male");
<div>
<input
type="radio"
name="gender"
className="border border-slate-500"
value={"male"}
defaultChecked
onChange={() => setRadioValue("male")}
/>
male
</div>
<div>
<input
type="radio"
name="gender"
className="border border-slate-500"
value={"female"}
onChange={() => setRadioValue("female")}
/>
female
</div>
select 요소 초기값 지정 시 defaultValue 속성 사용 가능
value와 defaultValue 차이점
const [selected, setSelected] = useState("apple");
<select value={selected} onChange={(e) => setSelected(e.target.value)}>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
</select>;
출처: 수코딩
진짜 깔끔하네요