하고 있는 프로젝트에서 select box를 클릭하면 나오는 dropdown에 option들이 보이는 개수를 5개로 지정해야 될 일이 있었다. 별거 아닌거 같지만 꽤 시간 들여 했어서... 기록한다 🙃
<select size={num}>
보이는 option들의 개수를 지정하고 싶을 때 사용하는 가장 간단한 방법이다. 하지만... 이 방법은 클릭했을 때 dropdown이 나오는 것이 아니라, 처음부터 지정한 개수로 dropdown이 펼쳐져 있다. 고로 나에게는 해결방법으로 적절하지 않았다.
간단한 데모: http://www.tcpschool.com/examples/tryit/tryhtml.php?filename=html_ref_tag_select_size_01
다른 방법이 있나 찾아보던 중에, stackoverflow에서 위와 같은 글을 봤다. 저 글 작성자분께서 소중한 데모 링크도 첨부해주셨다. (참고로 원글은 맨 아래 레퍼런스에 링크 남겨놨음!)
다만 나는 React로 만들어진 프로젝트 내에서 작업하므로 저대로 사용할 순 없다! 그치만 해결법은 찾은 이상 살짝 바꾸는 건 일도 아니다.
난 함수형 컴포넌트를 사용하고 있으므로 this를 사용할 수 없다. 대신 내가 가리키고자 하는 element를 지칭할 수 있도록 useRef를 사용해주면 된다. 그리고 아래와 같이 해주면 된다.
import { useRef } from 'react';
const SelectBox = (props: SelectBoxProps) => {
const selectBox = useRef() as React.MutableRefObject<HTMLSelectElement>;
return (
<>
<SelectBoxStyled {...props}>
<select
ref={selectBox}
onFocus={() => {
selectBox.current.size = 5;
}}
onBlur={() => {
selectBox.current.size = 1;
}}
onChange={(e) => {
selectBox.current.size = 1;
selectBox.current.blur();
}}
>
</SelectBoxStyled>
</>
);
};
export default SelectBox;
이제 select box를 클릭했을 때 dropdown에 내가 원하는 개수의 option들이 나온다. 하지만 이와 같은 방식은... 위 사진처럼... dropdown이 늘어나는 만큼 select box 자체가 늘어난다... 그래서 난 아래와 같이 수정해주었다.
//SelectBox.tsx
return (
<>
<SelectBoxStyled {...props}>
<div className="select-wrap">
<select { /*생략*/ }>
<option value="">{props.subject}</option>
{props.options ? props.options.map((option, idx) => (
<option key={idx} value={option}>{option}</option>
))
: null}
</select>
</div>
</SelectBoxStyled>
</>
);
//SelectBoxStyled.tsx
export const SelectBoxStyled = styled.div<SelectBoxProps>`
position: relative;
display: inline-block;
.select-wrap {
position: absolute;
}
select {
display: inline-block;
}
`;
position 속성을 활용해주었다. 그럼 가장 상단에 첨부했던 아름다운 select box가 나온다! (이게 뭐라고 2시간 동안 했다 ㅜㅜ) select box 커스텀 해본 건 처음이었는데 재밌는 경험이었당.
감사합니다!