Custom Selector
게시판 글 쓰기 페이지 구현 중, 문제가 발견되었다. API요청을 보낼 때,
main, sub 카테고리를 나눠서 보내야하는데, 기존에 <select>를 사용하면, sub카테로리는 불러와지지만, main을 불러올 수 없는 문제가 발생했다. 그래서 직접 구현해 보기로 했다.
작업 자체는 간단했다. boolean값으로 state를 주고, 해당 state가 false라면 CSS를 변경하는 코드를 작성하면 되는 것이었다.
해당 정보를 보여주는 콤보박스를 만드는 것이 목표
const boardList = [
{
id: 1,
main: '자유',
sub: ['잡담', '홍보'],
},
{
id: 2,
main: '멘토멘티',
sub: ['공부', '운동', '토익'],
},
{
id: 3,
main: '만남',
sub: ['친구', '밥약', '미팅'],
},
{
id: 4,
main: '장터',
sub: ['책', '중고', '자취방'],
},
];
state값을 주어서 열리고 닫히게 만들 것이다. 그리고 그 안에 map을 돌려서 값들을 불러와 줄 예정
const [ isCheckShow, setCheckShow ] = useState<boolean>(false);
return (
<div onClick={()=> setCheckShow(!isCheckShow)}>
<div>게시판</div>
<div>
{boardList.map((list)=>{
return (
<div>
{list.main}게시판
{list.sub.map((sub, idx)=>{
return <div onClick={}>{sub}</div>
}}
</div>
}}
</div>
</div>
onClick이벤트 시 state가 변경되도록 했다. 이제 여기에 CSS만 입히면 끝이다.
<SelectBox onClick={() => setCheckShow(!isCheckShow)}>
<Label>게시판</Label>
<SelectOptions show={`${isCheckShow}`}>
{boardList.map((list) => {
return (
<div key={list.id}>
{list.main}게시판
{list.sub.map((sub, idx) => {
return (
<Option key={idx}>
{sub}
</Option>
);
})}
</div>
);
})}
</SelectOptions>
SelectOptions 부분에 show라는 props를 전달해서 state값이 true일 때 콤보박스가 보여지게 만들었다.
CSS는 인터넷 여기저기서 긁으니깐 잘 나왔다ㅎ
/** selectbox container*/
const SelectBox = styled.div`
position: relative;
margin-left: auto;
width: 200px;
padding: 8px;
border-radius: 5px;
background-color: #ffffff;
align-self: center;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 25%);
cursor: pointer;
z-index: 1;
&::before {
content: '⌵';
position: absolute;
top: 1px;
right: 8px;
font-size: 20px;
}
`;
/** select title*/
const Label = styled.label`
font-size: 14px;
margin-left: 4px;
text-align: center;
`;
interface SO {
show: string;
}
/** state가 true라면 보여주게 만들기*/
const SelectOptions = styled.div<SO>`
position: absolute;
list-style: none;
top: 36px;
left: 0;
width: 100%;
overflow: hidden;
height: auto;
max-height: ${(props) => (props.show === 'true' ? 'none' : '0')};
padding: 0;
border-radius: 8px;
background-color: #222222;
color: #fefefe;
`;
const Option = styled.div`
font-size: 14px;
padding: 6px 8px;
transition: background-color 0.2s ease-in;
&:hover {
background-color: #595959;
}
`;
여기저기에서 긁어온 css를 우리 페이지 스타일에 맞게 고쳐주기만 하면 된다!
여기서 끝인줄 알았으나, 외부를 클릭했을 때, 콤보박스가 닫히지 않는 이슈가 생겼다!
어떻게 하면 좋을까 하다가 z-index를 사용해서 외부에 보이지않는 div를 만들어서 누르면 닫히게 만들 예정이다!
{isCheckShow && (
<DropDown
onClick={(e: React.MouseEvent) => {
e.preventDefault();
if (isCheckShow) {
handleClose();
}
}}></DropDown>
)}
const DropDown = styled.div`
background-color: rgba(f, f, f, 100%);
position: fixed;
z-index: -1;
left: 0px;
top: 0px;
width: 10000px;
height: 1000px;
cursor: auto;
`;
해당 코드를 SelectBox내부에 추가해주고, handleClose함수를 만들어서 작동되게 했다.
const handleClose = () => {
setCheckShow(!isCheckShow);
}
이렇게 하니깐 잘 작동된다!
