input type="checkbox"를 버튼 형태로 렌더링한 영역을 클릭했을 때 다음과 같은 에러가 발생:

⇒ React는 처음에는 uncontrolled로 보이는데 나중에 값이 생기면서 갑자기 controlled로 바뀌니 혼란스러운 상황이라고 경고를 날리고 있는 것입니다.
React는 폼 요소(input, textarea, select 등)가 처음 렌더링될 때부터 제어 방식이 일관되어야 한다는 원칙을 가지고 있습니다.
React에서는 <input> 같은 폼 요소를 두가지 방식으로 관리합니다.
| 타입 | 설명 | 예시 |
|---|---|---|
| Uncontrolled (비제어) | 리액트가 값을 직접 관리하지 않고, DOM 자체에 값 저장 | <input defaultValue="hi" /> |
| Controlled (제어) | 리액트 상태(state)로 값을 제어 | <input value={someState} onChange={...} /> |
const [watch, setWatch] = useState({
checked: {},
startDate: '',
endDate: '',
comment: '',
}
<form onSubmit={handleSubmit}>
{formField.map((field, idx) => (
<FormControl key={idx} label={field.label} inputType={field.type}>
{field.type === 'buttonsCheck' &&
field.options.map((option, i) => {
return (
<span key={i}>
<Button
styleType={selected ? 'brandSolid' : ''}
text={option}
onClick={e => {
e.preventDefault();
handleCheckbox(field.label, option);
}}
/>
<input
type="checkbox"
name={field.label}
id={`${field.label}-${option}`}
value={option}
checked={checked[field.label]?.includes(option,);}
onChange={() => handleCheckbox(field.label, option)}
/>
</span>
);
})}
</FormControl>
))}
</form>
현재 코드에서는checked[field.label]가 초기에 undefined 상태로 비제어(Uncontrolled) 로 인식하였는데 나중에 값이 생기면 제어(Control) 상태로 바뀌게 되어 경고 발생한 것입니다.
checked[field.label] 의 값이 undefined 이더라도 안전하게 처리될 수 있도록 빈 배열로 기본값을 설정해주었습니다.
<input
type="checkbox"
name={field.label}
id={`${field.label}-${option}`}
value={option}
checked={(checked[field.label] || [])?.includes(option);}
onChange={() => handleCheckbox(field.label, option)}
/>