컴포넌트와 상태
state는 동적인 리액트 컴포넌트로 state의 값에 따라 다른 결과를 렌더링 한다. 사용자의 행위나 시간 변동에 따라 값이 변한다.
const [ state, setState ] = useState(초깃값);
- state : state 변수, 형재 상태
- setState : set 함수, state를 변경하는 함
- useState() : 생성자(초깃값)
useState 인자로 값을 넣어주면 state와 setState의 2가지 요소를 배열 형태로 리턴해 준다. state를 변경시켜 주고 싶을 땐 setState 함수를 이용해서 간편하게 변경시켜 줄 수 있다.
const [ light, setLight ] = useState(4);
- State : light = 4
- setLight(5) ➡️ light = 5
- setState 함수로 state를 변경하면 해당 컴포넌트는 화면에 다시 업데이트(렌더링) 된다.
🌏 [set 함수로 State 값 변경하기]
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;
- 버튼의 이벤트 핸들러 onIncrease에서는 set 함수인 setCount를 호출한다. 인수로 count에 1 더한 값을 전달한다.
- set 함수를 호출해 State 값을 변경하면, 변경값을 페이지에 반영하기 위해 컨포넌트를 다시 렌더링한다.
- 컴포넌트가 페이지에 렌더링하는 값은 컴포넌트 함수의 반환값이다.
- 컴포넌트를 다시 렌더링 = 컴포넌트 함수를 다시 호출한다는 의미

- 컴포넌트는 자신이 관리하는 State 값이 변하면 다시 호출된다.
- 그리고 변경된 State 값을 페이지에 렌더링한다.
- State 값이 변해 컴포넌트를 다시 렌더링하는 것을 '리렌더' 또는 '리렌더링'이라고 한다.
- 리액트 컴포넌트는 자신이 관리하는 State 값이 변하면 자동으로 리렌더된다.
- <input> 태그로 텍스트 입력하기
- <input>은 폼이 다양해서 type 속성을 지정하여 사용
- text, date, tel, radio, checkbox etc
- 아무 것도 입력하지 않은 기본 입력 폼은 text
- <input> 태그로 날짜 입력하기
- type="date"
- e.target.value에는 yyyy-mm-dd 형식의 날짜 저장
- 드롭다운 상자로 여러 옵션 중에 하나 선택하기
- <select>와 <option> 함께 사용
- 목록 하나를 선택하면 해당 항목 입력할 수 있다.
- option에 key={"값"} 속성 설정해줘야 한다.
- e.target.value에는 현재 사용자가 선택한 옵션의 key 저장
- 글상자로 여러 줄의 텍스트 입력하기
- <textarea>
- <input> 태그의 입력 폼과 동일한 형태
- e.target.value에 저장된 값을 인수로 전달해 state 값 변경
🌏 [여러 개의 사용자 입력 관리하기]
1) 관리할 state 수가 많아 코드가 길어진다.
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) => {
setName(e.target.value);
};
const onChangeBio = (e) => {
setName(e.target.value);
};
return (
<div>
<div>
<input value={name} onChange={onChangeName} placeholder"이름" />
</div>
<div>
<select key={gender} onChang={onChangeGener}>
<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;
2) 객체 자료형을 이용해서 하나의 state로 관리
import { useState } from "react";
function Body() {
const [state, setState] = useState({ 📌 1
name: "",
gender: "",
birth: "",
bio: "",
});
const handleOnChange = (e) => {
console.log("현재 수정 대상:", e.target.name);
console.log("수정 값:", target.value);
setState({ 📌
...state,
[e.target.name]: e.target.value,
});
};
return (
<div>
<div>
<input
name="name" 📌 2
value={state.name} 📌 3
onChange={handleOnChange} 📌 4
placeholder="이름"
/>
</div>
<div>
<select name="gender" key={state.gender} onChang={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를 하나 생성하고 초깃값을 설정한다.
- 모든 입력 폼에 name 속성을 지정
- name="gender"
- 모든 입력 폼의 value 를 객체 state의 프로퍼티 중 하나로 설정
- 예를 들면, value={state.gender} 지정
- 객체 state의 name 프로퍼티와 동일한 값으로 설정
- 사용자의 입력을 처리할 이벤트 핸들러 설정
setState({
...state,
[e.target.name]: e.target.value,
});
- 함수 setState에서는 새로운 객체를 생성해 전달한다.
- 스프레드 연산자를 이용해 기존 객체 state의 값 나열(...)
- 객체의 괄호 표기법을 사용하여 입력 폼의 name 속성(e,target.name)을 key로 설정
- 입력폼에 입력한 값(e.target.value)을 value로 사용
💡
- e.target.name이 현재 이벤트 발생한 요소의 name 속성
- 만약 <select>에서 이벤트가 발생했다면, e.target.name은 gender가 된다.
- 객체 state의 프로퍼티 중 현재 이벤트가 발생한 요소인 프로퍼티의 value 값을 변경하게 된다.
🌏 [Props와 State]
동적으로 변하는 값인 리액트의 State 역시 일종의 값이므로 Props로 전달할 수 있다.
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;
- Viewer 컴포넌트를 선언한다. 이 컴포넌트에는 Props로 Body 컴포넌트에 있는 State 변수 number가 전달된다.
- Viewer 컴포넌트는 조건부 렌더링을 이용해 변수 number의 값을 평가하고, 값에 따라 짝수 혹은 홀수 값을 페이지에 렌더링한다.
- Body에서 Viewer를 자식 컴포넌트로 사용하며, Props로 변수 number를 전달한다.
📒 알 수 있는 중요한 사실
자식 컴포넌트는 Props로 전달된 State 값이 변하면 자신도 리렌더된다는 사실이다. 즉, 부모에 속해 있는 State(number) 값이 변하면 Viwer 컴포넌트에서 구현한 '짝수', '홀수' 값도 따라서 변한다.

⚠️ 나만 알아 보는 코드.....뜯어 보기........... 연습^^!!!!!!!
import { useState } from "react";
const heavyWork = () => { 📌무거운 작업을 하는 함수
return ['콩', '두부'];
};
function App () {
const [names, setNames] = useState(() => { 📌콜백 함수를 넣어 리턴 값으로 무거운 작업을 하는 함수를 불러 준다.
return heavyWork();
});
const [input, setInput] = useState('');
const handleInputChange = () => {
setInput(e.target.value);
};
const handleUpload = (prevState) => { 📌
setNames(() => {
return([input, ...prevState]);
});
};
return (
<div>
<input type="text" value={input} onChange={handleInputChange} />
<button onClick={handleUpload}>업로드</button>
{names.map((name, idx) => {
return <p key={idx}>{name}</p>;
})}
</div>
);
}
export default App;
[정리]
1)
setState((prevState) => {
// some works...
return newState;
});
- state를 변경할 때 새로 변경될 state 값이 이전 state 값과 연관이 되어 있다면 setState의 인자로 새로운 state를 리턴하는 콜백 함수를 넣어주는 것이 좋다.
2)
useState(() => {
return heavyWorks();
})
- useState를 사용해서 초깃값을 받아올 때 무거운 작업을 해야 한다면 useState의 인자로 콜백 함수를 넣어 준다면 맨 처음 렌더링이 될 때만 실행되게 할 수 있다.
📕참고: 한 입 크기로 잘라 먹는 리액트 - 이정환
📕참고: useState _유튜브 별코딩
'기술 > React' 카테고리의 다른 글
| [React] 리액트의 데이터 흐름 (0) | 2024.02.27 |
|---|---|
| [React] useRef - 리액트에서 DOM 조작하기 (0) | 2024.02.27 |
| [React] Props - 컴포넌트에 값 전달하기 (0) | 2024.02.27 |
| [React] JSX (0) | 2024.02.27 |
| [React]재렌더링이 발생하는 조건 (0) | 2024.02.27 |