[React] State로 사용자 입력 관리하기
회원가입 폼 렌더링해보기
import { useState } from 'react';
- useState는 React의 상태 관리를 위한 Hook인데,
- App.js 파일 안이나 Register 컴포넌트 안에서 사용되지 않았음.
- 사용하지 않는 import는 보통 경고가 뜨거나 불필요한 코드가 되니까 삭제해도 무방
그럼 언제 사용하냐?
seState는 "상태를 저장하고 바꾸고 싶을 때" 사용해!
예를 들어 버튼을 클릭하면 숫자가 올라가는 기능을 만들때
상황 | useState 써야 할까? |
버튼 누르면 값이 바뀌어야 해 | o |
입력창에 글 쓰면 실시간으로 상태 저장 | o |
어떤 요소를 숨기거나 보여주고 싶을 때 | o |
단순히 텍스트/컴포넌트 보여주기만 할 때 | x |
import { useState } from 'react';
// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개
const Register = () => {
// 초- 초기 값 설정하고 싶으면 useState('여기에 적기');
const [name, setName] = useState('이름');
const [birth, setBirth] = useState('');
const [country, setCountry] = useState('');
const [bio, setBio] = useState('');
const onChangeName = (e) => {
// console.log(e);
// e.target.value; // value 프로퍼티에 접근하면 현재 사용자가 작성한 텍스트에 접근 가능
setName(e.target.value);
};
const onChangeBirth = (e) => {
setBirth(e.target.value);
};
const onChangeCountry = (e) => {
setCountry(e.target.value);
};
const onChangeBio = (e) => {
setBio(e.target.value);
};
return (
<div>
{/* div로 감싸면 한 줄씩 보여준다. */}
<div>
{/* 초 - input태그의 value 속성으로 이 state인 name 설정하기 */}
<input value={name} onChange={onChangeName} placeholder={'이름'} />
{/* 입력 값 보여줌 */}
{/* {name} */}
</div>
<div>
{/* date picker 렌더링 */}
<input value={birth} onChange={onChangeBirth} type="date" />
</div>
<div>
{/* select는 기본으로 맨 위에 있는 옵션이 됨, 만일 아무것도 안하고 싶으면 빈 옵션 넣기 */}
<select value={country} onChange={onChangeCountry}>
<option></option>
{/* value로 더 간결한 값을 사용하는 경우가 많다. */}
<option value="kr">한국</option>
<option>미국</option>
<option>일본</option>
</select>
</div>
<div>
<textarea value={bio} onChange={onChangeBio} />
</div>
</div>
);
};
export default Register;
onChange 속성말고도 value 속성도 함께 적용해주기
State로 사용자 입력 관리하기
✅ 4개의 state를 하나의 객체로 묶기
import { useState } from 'react';
// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개
const Register = () => {
// 상태 초기화 -> 하나의 객체로 만듦
const [input, setInput] = useState({
name: '',
birth: '',
country: '',
bio: '',
});
// input의 값 어떻게 변경되는지 확인 가능
console.log(input);
const onChangeName = (e) => {
setInput({ ...input, name: e.target.value });
};
const onChangeBirth = (e) => {
setInput({ ...input, birth: e.target.value });
};
const onChangeCountry = (e) => {
setInput({ ...input, country: e.target.value });
};
const onChangeBio = (e) => {
setInput({ ...input, bio: e.target.value });
};
return (
<div>
{/* div로 감싸면 한 줄씩 보여준다. */}
<div>
<input
value={input.name}
onChange={onChangeName}
placeholder={'이름'}
/>
</div>
<div>
{/* date picker 렌더링 */}
<input value={input.birth} onChange={onChangeBirth} type="date" />
</div>
<div>
{/* select는 기본으로 맨 위에 있는 옵션이 됨, 만일 아무것도 안하고 싶으면 빈 옵션 넣기 */}
<select value={input.country} onChange={onChangeCountry}>
<option></option>
{/* value로 더 간결한 값을 사용하는 경우가 많다. */}
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="jp">일본</option>
</select>
</div>
<div>
<textarea value={input.bio} onChange={onChangeBio} />
</div>
</div>
);
};
export default Register;
여러개의 state로 나눠서 관리하든 4가지의 데이터를 객체 형태로 만들어 하나의 state로 만들었다.
✅이벤트 핸들러도 하나로 묶기
import { useState } from 'react';
// 간단한 회원가입 폼
// 1. 이름
// 2. 생년월일
// 3. 국적
// 4. 자기소개
const Register = () => {
// 상태 초기화 -> 하나의 객체로 만듦
const [input, setInput] = useState({
name: '',
birth: '',
country: '',
bio: '',
});
// input의 값 어떻게 변경되는지 확인 가능
console.log(input);
const onChange = (e) => {
setInput({
...InputDeviceInfo,
[e.target.name]: e.target.value,
});
};
return (
<div>
{/* div로 감싸면 한 줄씩 보여준다. */}
<div>
<input
name="name"
value={input.name}
onChange={onChange}
placeholder={'이름'}
/>
</div>
<div>
<input
name="birth"
value={input.birth}
onChange={onChange}
type="date"
/>
</div>
<div>
{/* select는 기본으로 맨 위에 있는 옵션이 됨, 만일 아무것도 안하고 싶으면 빈 옵션 넣기 */}
<select name="country" value={input.country} onChange={onChange}>
<option></option>
{/* value로 더 간결한 값을 사용하는 경우가 많다. */}
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="jp">일본</option>
</select>
</div>
<div>
<textarea name="bio" value={input.bio} onChange={onChange} />
</div>
</div>
);
};
export default Register;
🔎 코드 동작 방법 살펴보기
1. input, select, textarea에 onChange를 모두 같은 함수로 설정했기 때문에 → 어디에 입력을 하든지 공통 onChange 함수가 실행
<input name="name" onChange={onChange} />
<input name="birth" onChange={onChange} />
<select name="country" onChange={onChange} />
<textarea name="bio" onChange={onChange} />
2. 그럼 onChange(e)가 실행될 때
const onChange = (e) => {
setInput({
...input,
[e.target.name]: e.target.value,
});
};
setInput()이 실행된다
그리고 이 안에 있는 객체는 스프레드 문법(...input)으로 기존 상태를 복사한 후
[e.target.name]이라는 프로퍼티 키에 e.target.value 값을 넣는다
3. [e.target.name] 부분 (핵심)
자바스크립트에서 객체의 키 자리에 [ ] 대괄호를 쓰면 그 안에 있는 값이 키가 된다
예) e.target.name이 "birth"라면 → 결국 birth: e.target.value가 된다!
4. 예시 흐름 하나 따라가 봄
<input name="birth" onChange={onChange} />
사용자가 생년월일을 입력했을 때 → 그 입력창은 name="birth"로 되어 있음
그래서 e.target.name은 "birth" → 입력한 값은 e.target.value, 예: "2000-01-01"
그러면 setInput은 이렇게 실행됨:
setInput({
...input,
birth: '2000-01-01'
});
6. 이렇게 하면 결과적으로
입력 필드의 name 속성에 따라 해당 필드 이름을 키로 쓰고 입력한 값을 그 키에 맞춰서 바꾸는 코드가 되는 것!
즉, 모든 필드에 대해서 onChange 하나로 처리 가능!
📝 setInput은 input 상태를 갱신하는 함수고, e.target.name을 객체의 키로 쓰고,
e.target.value를 그 키의 값으로 지정해서 전체 input 상태를 하나의 객체로 관리하는 패턴
이 패턴을 쓰면 여러 입력 필드를 하나의 핸들러로 통합해서 깔끔하게 처리할 수 있다.