드랍다운은 디자인하기가 까다롭다.
리액트 스테이트를 이용해 드랍다운을 디자인했다.
useRef를 이용해서 바깥을 클릭하면 드랍다운 창이 꺼진다.
import React, { useEffect, useRef, useState } from 'react';
import { TiArrowSortedDown } from 'react-icons/ti';
import styled from 'styled-components';
const VideoFilterDropdown = ({ scrollProp, setScrollProp }) => {
const [Dropped, setDropped] = useState(false);
const [selected, setSelected] = useState('');
const categoryArray = ['전체', '목', '허리', '전신'];
useEffect(() => {
if (typeof selected !== 'number') return;
setScrollProp({ ...scrollProp, category: selected, page: 0 });
}, [selected]);
const ref = useRef();
const handleClickOutSide = (e) => {
if (Dropped && !ref.current.contains(e.target)) {
setDropped(false);
}
};
useEffect(() => {
if (Dropped) document.addEventListener('mousedown', handleClickOutSide);
return () => {
document.removeEventListener('mousedown', handleClickOutSide);
};
});
return (
<DropdownWrapper ref={ref}>
<Selected
onClick={() => {
setDropped(!Dropped);
}}
>
{typeof selected === 'number' ? categoryArray[selected] : '카테고리'}
<span
style={
Dropped ? { transform: 'translateY(-50%) rotate(180deg)' } : {}
}
>
<TiArrowSortedDown />
</span>
</Selected>
<DropDownlist style={Dropped ? {} : { visibility: 'hidden' }}>
{categoryArray.map((e, idx) => {
return (
<ListItem
key={e}
onClick={() => {
setSelected(idx);
setDropped(false);
}}
>
{e}
</ListItem>
);
})}
</DropDownlist>
</DropdownWrapper>
);
};
export default VideoFilterDropdown;
const DropdownWrapper = styled.div`
margin-left: 0.1rem;
margin-right: 0.5rem;
width: 6rem;
`;
const Selected = styled.div`
text-align: center;
background-color: ${(props) => props.theme.color.secondary};
color: ${(props) => props.theme.color.primary};
font-weight: bold;
padding: 0.3rem;
border-radius: 0.5rem;
border: 0.1rem solid ${(props) => props.theme.color.primary};
box-shadow: 0 0.1rem 0.5rem ${(props) => props.theme.color.lightGrayColor};
cursor: pointer;
span {
position: absolute;
display: flex;
top: 8.2rem;
left: 4.9rem;
font-size: 0.9rem;
align-items: center;
transform: translateY(-50%);
width: 1rem;
opacity: 0.7;
transition: 0.2s ease;
}
`;
const DropDownlist = styled.div`
width: 6rem;
position: absolute;
z-index: 2;
`;
const ListItem = styled.div`
text-align: center;
background-color: ${(props) => props.theme.color.whiteColor};
cursor: pointer;
color: ${(props) => props.theme.color.primary};
font-weight: bold;
padding: 0.3rem;
border-radius: 0.5rem;
border: 0.1rem solid ${(props) => props.theme.color.primary};
box-shadow: 0 0.1rem 0.5rem ${(props) => props.theme.color.lightGrayColor};
&:hover {
background-color: ${(props) => props.theme.color.secondary};
}
`;
onKeyDown 이벤트를 이용해 일반 인풋 태그에서 엔터를 누르면 요청이 가도록 했다.
Form 태그를 이용하는 것이 가장 좋지만, 미처 form 태그를 적용하지 못한 경우에 사용하면 좋다.
onKeyDown, onKeyUp은 Keycode값이고, onKeyPress는 ASCII 값이다
출처
onKeyPress는 deprecated 되었다.
return (
<InputWrapper>
<StyledInput
autoFocus
id="nickname-input"
value={nicknameInput}
onChange={(e) => setNicknameInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') onSubmit();
}}
/>
</InputWrapper>
)
const InputWrapper = styled.div`
font-size: 1.2rem;
font-weight: bold;
color: ${(props) => props.theme.color.primary};
`;
const StyledInput = styled.input`
text-align: right;
`;