useState 사용법 3번째 글이다.
이번엔 form 태그와 input 태그로 참조형 스테이트를 제어하는 방법을 정리해보고자 한다.
간단한 메모 기능을 구현하며 정리해보겠다.
알아야 할 Javascript 문법
- useState() 기본 사용법
- 구조 분해 할당, 스프레드 연산자
state 자료 구조
- memos = [ { id, memo, isChecked }, { id, memo, isChecked }, ... ];
배열[ 객체1, 객체2, ... ] => 주요 메모 데이터
2. todo = '문자열' => memos에 추가될 객체의 memo 프로퍼티에 할당 될 데이터
setState 호출 정리
- setMemos : form 태그의 onSubmit 그리고 button 태그의 onClick 이벤트로 'setMemos' 함수 호출
2. setTodo : input 태그의 onChange 이벤트로 'setTodo' 함수 호출
// 초기 데이터를 변수로 선언
const initialMemos = [
{
id : 0,
memo : '돈벌기',
isChecked : false
},
{
id : 1,
memo : '주식 투자하기',
isChecked : false
},
...
];
// 'memos' state 할당.
const [memos, setMemos] = useState( initialMemos );
// 'todo' state 할당
const [todo ,setTodo] = useState('');
return (
<div style={style.div}>
// 체크되지 않은 메모 리스트 제목
<h1>해야할 일</h1>
<ol>
// 'memos' state를 map 함수로 접근해 요소 랜더링
{memos.map((item)=> {
if(!item.isChecked){
// isChecked의 값이 false(체크되지 않은)인 객체인 경우
// li 요소를 리턴
return (<li key={item.id}>
// input=[checkbox]의 onChange => handleCheck 함수에 event 와 데이터 id 값 전달하여 호출
<input id={`chk${item.id}`} type="checkbox" value={true} onChange={(e)=>handleCheck(e, item.id)} />
<label htmlFor={`chk${item.id}`}>{item.memo}</label>
</li>);
}else{
// isChecked의 값이 true(체크된)인 객체인 경우 display : none 속성을 부여한다.
// 빈 값을 리턴하는 경우 li 요소 리턴이 아니기 때문에 경고 출력
// 따라서 filter로 제한사항을 두거나 한 줄 삼항 연산자 사용 권장됨
return (<li key={item.id} style={style.none}></li>);
}
})}
</ol>
// input=[text] 태그의 onSubmit => handleSubmit 함수 호출
<form onSubmit={handleSubmit}>
// onChange => handleChangeTodo 함수 호출
// input 요소의 value 속성을 'todo'(제어할 스테이트)로 할당해주어야 값 변경 가능!
<input type="text" value={todo} onChange={handleChangeTodo} placeholder='추가할 메모를 적어주세요' />
<button type="submit"> 메모 추가하기 </button>
</form>
// 체크된 메모 리스트 제목
<h2>완료한 일</h2>
<ul>
// isChecked의 값이 true(체크된)인 객체인 경우
// li 요소를 리턴
{memos.map((item) => (item.isChecked&&<li key={item.id}> {item.memo} </li>))}
</ul>
</div>
);
// 1. input=[text] 태그의 onChange 이벤트로 호출되는 함수로 'todo'를 제어
const handleChangeTodo = (e) => {
// setTodo 호출하여 'todo' 변경!
// input 태그에 값을 입력하면
// 이벤트 target(input)의 value값을 'todo'에 할당
setTodo(e.target.value);
}
// form 태그의 onSubmit 이벤트로 호출되는 함수로 'memos' 와 'todo'를 제어
const handleSubmit = (e) => {
// preventDefault() 메서드로 form 태그의 submit 이벤트를 막는다.
e.preventDefault();
// 'memos'에 추가할 id 값과 객체를 구현한다. memo 프로퍼티의 value는 'todo'(state)값으로 할당한다.
// 추가될 객체의 id 값은 memos의 길이로 할당한다.
const id = parseInt(memos.length);
const obj = {
id,
// memo 프로퍼티의 값은 'todo'(입력된 state) 값으로 할당
memo : todo,
isChecked : false
}
// setMemos 호출하여 'memos' 변경!
// 이전 state(memos) 값에 객체를 추가해준 배열을 리턴
setMemos((prev) => ( [ ...prev, {...obj} ] );
// setTodo 호출하여 'todo' 변경!
// 'todo'(input태그의 value 속성값)를 빈 문자열로 할당한다.
setTodo('');
}
// input=[checkbox] 태그의 onChange 이벤트로 호출되는 함수로 'memos'를 제어
const handleCheck = (e, id) => {
// setMemos 호출하여 'memos' 변경!
setMemos((prev) => {
// 이전 스테이트 값을 복사하여 변수로 할당
const result = [...prev];
// 일부(isChecked)값만 변화시킨다.
result[id]["isChecked"] = e.target.value;
// 수정 완료된 배열을 리턴해 'memos'스테이트에 할당
return [ ...result ];
});
}
함수형 컴포넌트에서 state를 구현하는 방법을 정리해봤다.
더 자세한 state 사용 규칙도 정리할 필요가 있겠다.
다음 글은 useEffect를 정리해 보도록 하겠다.