[⚠️] <select> 요소의 defaultValue 와 value 는 함께 정의하면 안된다?

BinaryWoo_dev·2023년 6월 10일
0

html

목록 보기
2/2

서론


jest 라이브러리를 통해 Custom Select Filter 컴포넌트 UI 테스트를 진행하는 도중 아래와 같은 에러를 맞이하였다. 😵

  console.error
    Warning: Select elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled select element and remove one of these props. More info: https://reactjs.org/link/controlled-components
        at select
        at options (/Users/leejinw/Documents/codes/ljw/project/project--recommend-recipes--nextjs/client/components/Modules/Select.tsx:16:2)
        at div
        at div
        at div
        at div
        at spinning (/Users/leejinw/Documents/codes/ljw/project/project--recommend-recipes--nextjs/client/components/Modules/Loading.tsx:5:20)
        at div
        at div
        at div
        at MainComponent (/Users/leejinw/Documents/codes/ljw/project/project--recommend-recipes--nextjs/client/components/Home/index.tsx:35:15)
        at homePage

       5 | describe('Home page UI 렌더링 Test', () => {
       6 |      it('1. Description UI', () => {
    >  7 |              render(<HomePage />);
         |               ^
       8 |              expect(1 + 1).toBe(2);
       9 |      });
      10 | });

Modules/Select.tsx

import React from 'react';

export type optionType = {
	label: string;
	value: string | number;
};

interface SelectProps {
	options: Array<optionType>;
	isExistAll?: Boolean;
	onChange: Function;
	value: number;
}

const Select = ({
	options,
	isExistAll,
	onChange,
	value
}: SelectProps): JSX.Element => {
	return (
		<select
			className='select w-full max-w-xs'
			onChange={(e) => onChange(e.currentTarget.value)}
			defaultValue={0}
			value={value}>
			{isExistAll && <option value={0} label='전체' />}
			{options &&
				options?.map((item: optionType) => (
					<option key={item?.value} value={item?.value} label={item?.label} />
				))}
		</select>
	);
};

export default Select;

본론


에러 메세지를 보며 원인을 분석해보니 핵심 문구는 다음과 같았다.

specify either the value prop, or the defaultValue prop, but not both

위의 문구를 참조하여 Custom Select Filter 코드를 다시 한 번 확인하였더니 <select> 태그에 defaultValue, value 두 prop이 모두 정의되어 있었다.

value는 현재값이 초기화되지 않고 유지되도록, defaultValue는 최초 렌더링 시, 초기 선택값을 설정하기 위해 정의하였었는데 value prop 만으로 defaultValue prop 역할까지 대체할 수 있었다.
따라서, 아래와 같이 수정하였더니 더 이상 테스트 에러가 발생하지 않았다.

import React from 'react';

export type optionType = {
	label: string;
	value: string | number;
};

interface SelectProps {
	options: Array<optionType>;
	isExistAll?: Boolean;
	onChange: Function;
	value: number;
}

const Select = ({
	options,
	isExistAll,
	onChange,
	value
}: SelectProps): JSX.Element => {
	return (
		<select
			className='select w-full max-w-xs'
			onChange={(e) => onChange(e.currentTarget.value)}
-           // defaultValue={0}
-			// value={value}
+			value={value ?? 0}>
			{isExistAll && <option value={0} label='전체' />}
			{options &&
				options?.map((item: optionType) => (
					<option key={item?.value} value={item?.value} label={item?.label} />
				))}
		</select>
	);
};

export default Select;

결론


  • <select> 태그에는 defaultValue, value prop을 동시에 선언하는 것을 지양해야 한다.
profile
매일 0.1%씩 성장하는 Junior Web Front-end Developer 💻🔥

0개의 댓글