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을 동시에 선언하는 것을 지양해야 한다.