[Material UI] Radio Input 클릭시 checked가 반영되지 않는 문제

서해빈·2021년 5월 12일
0

Trouble

목록 보기
13/15
post-custom-banner

발단: Radio Input 클릭해도 checked 속성이 추가되지 않음

Material UI의 RadioGroup, Radio Component를 사용해 radio input을 구성했다. input을 클릭했을 때 formik의 state속 values의 값은 잘 반영되었지만 정작 <input type="radio" \>에서 checked 속성이 추가되지 않는 문제가 있었다.

원인: 문서의 의도와 일치하지 않는 내부 구현

며칠에 걸친 구글링 끝에 우연히 input의 value를 문자열로 넘기면 정상적으로 작동한다는 사실을 알 수 있었다.

분명 공식 문서에서는 Radio Component의 value 속성으로 어떤 값이든 올 수 있다고 되어있고, 내부적으로 문자열로 형변환된다고 나와있었기 때문에 매우 혼란스러웠다.

어디서 문제가 되는지 확인해야하는데 Formik과 Material UI를 같이 쓰고 있었기 때문에 어디서부터 손대야할지 막막했다... 이틀 정도 두 라이브러리를 헤집다가 Radio Component에서 checked 값을 할당하는 부분이 원인이었음을 확인했다.

// @material-ui/core/Radio/Radio.js
...
var Radio = /*#__PURE__*/React.forwardRef(function Radio(props, ref) {
  var checkedProp = props.checked,
  ...
  var radioGroup = (0, _useRadioGroup.default)();
  var checked = checkedProp;
  ...
  
  if (radioGroup) {
    if (typeof checked === 'undefined') {
      // 전자는 형변환된 문자열, 후자는 숫자형이므로 false가 할당된 것이었다;;
      checked = radioGroup.value === props.value;
    }

    if (typeof name === 'undefined') {
      name = radioGroup.name;
    }
  }
  
  return ...
}

사실 2017년도에 closed된 issue에서 원래는 문서에서 value의 타입을 문자열로 명시했음을 확인할 수 있었다. 해당 이슈에 number도 허용해도 괜찮을 것 같다는 답변이 있는 것으로 보아 이후에 수정된 것으로 보이는데, 정작 내부 코드에서는 원래 값과 (native onchange에 의해) stringified된 값을 Identity Operator(===)로 비교해 checked 여부를 결정하고 있었다.

cf) radio input의 value 속성은 DOMString이다. MDN Web 문서에 따르면 Web API는 DOMString을 받을 때, ToString을 사용해 value를 문자열화 한다고 한다. 때문에 radio의 value에 숫자형 값으로 전달해도 DOM에서는 value가 문자열임을 확인할 수 있다.

해결: 처음부터 문자열 값을 value 속성으로 전달

그냥 form 내부의 radio에서 사용되는 모든 value 속성에 문자열을 전달하는 것으로 통일했다. 이후 정상적으로 동작하는 것을 확인할 수 있었다.

참고 및 출처

post-custom-banner

0개의 댓글