[⚠️ ERROR] React에서 "uncontrolled input to controlled" 경고 해결하기

zzincode·2025년 4월 21일
0

ReviewZIP

목록 보기
6/7

🚨 에러 상황

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)}
  />

0개의 댓글