์ด์ ์ react์์ ์ ๊ณตํ๋ dropdown ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ปค์คํ ํ ์ ์ด ์๋ค.
ํ์ง๋ง ๋ด๊ฐ ์ด๋ฒ์ ๋ง๋ค์ด์ผ ํ๋ ๋๋กญ๋ค์ด์ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ปค์คํ ํด์๋ ํ ์ ์์๋ค.
์ฝ 20๋ถ์ ๋ ํด๋ณด๊ณ ์๋๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด๊ธฐ ์์ํ๋ค.
๋ด๊ฐ ํ๊ณ ์ถ์ ๊ฑด, ์์ด์ฝ์ ๋๋ ์ ๋ ๋๋กญ๋ฐ์ค๊ฐ ๋์ค๋ ๊ฒ์ด์๋๋ฐ ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ดค์ผ๋, ๊ตฌ๋ ์ ํ๊ฑฐ๋ ๋์ ๋ด์ผ ์ฌ์ฉํ ์ ์๋ ๋ถ๋ถ์ด์๋ค.
๊ณ ๋ฏผ ๋์ ๊ทธ๋ฅ ๋ง๋ค๊ธฐ๋ก ํ๋ค.
๋๋ต์ ์ธ ์๊ฐ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. ์์ด์ฝ ๋ฒํผ์ ์์ฑํ๋ค.
2. ๋ฒํผ์ ํด๋ฆญ ํ์ ๋ dropdown์ ๋ณด์ฌ์ค๋ค.
3. dropdown ์ปจํ ์ด๋ ์์ ๊ฐ list์ ๋ผ์ฐํฐ๋ฅผ ์ฐ๊ฒฐํด ์ํ๋ ํ์ด์ง๋ก ์ด๋์ํจ๋ค.
1. ์์ด์ฝ ๋ฒํผ ์์ฑํ๊ธฐ
์ด๋ถ๋ถ์ ์์ ํ ui ์์ญ์ด๊ธฐ์ ๊ทธ๋ฅ ๋ด๊ฐ ์ฌ์ฉํ ์์ด์ฝ ๋ฒํผ ์ฝ๋๋ฅผ ๋ฃ์ด๋๊ฒ ๋ค.
<ProfileButton
onClick={toggleDropdown}
style={{ backgroundColor: "transparent" }}
>
{/* */}
<AccountCircleIcon
sx={{
fontSize: "30px",
color: "white",
paddingTop: "5px",
paddingLeft: "20px",
paddingRight: "80px",
}}
/>
</ProfileButton>
const ProfileButton = styled.button`
text-align: center;
background-color: ${theme.colors.background};
color: ${theme.colors.white1};
border-color: transparent;
width: 35px;
height: 35px;
margin-right: 130px;
`;
2. ๋ฒํผ ํด๋ฆญ ์ dropdown ๋ณด์ฌ์ฃผ๊ธฐ
2-1. ์ํ ๊ด๋ฆฌ
์ด๋ฅผ ํ๊ธฐ ์ํด์๋ ์ํ๊ด๋ฆฌ๋ฅผ ํ ์ ์๋ useEffect๊ฐ ํ์ํ๋ค.
๋ฒํผ์ด ๋๋ ธ๋์ง, ์๋๋ ธ๋์ง์ ๋ฐ๋ผ ๋ค๋ฅธ ํ๋ฉด ์ํ๋ฅผ ๋ณด์ฌ์ค์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
์ด๋ฅผ ์ํด ๋จผ์ false๋ก ์ด๊ธฐํ ๋ isDropdownOpen ์ด๋ผ๋ ์ํ ๋ณ์๋ฅผ ์์ฑํ์๋ค.
์ด ๋ณ์๋ dropdown์ด ์ด๋ ค ์๋์ง, ๋ซํ ์๋์ง๋ฅผ ๋ํ๋ธ๋ค. ์์ํ๋ฏ, false๋ ๋ซํ ์ํ์ด๊ณ , true๋ ์ด๋ฆฐ ์ํ์ด๋ค.
๋ค์์ผ๋ก setIsDropdownOpen์ด๋ผ๋ ํจ์๋ฅผ ์ฐ๊ฒฐํ๋๋ฐ, ์ด ํจ์๋ฅผ ํตํด isDropdownOpen์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
const ref = useRef(null);
useRef๋ ๋๋ ์์ง ๊ณต๋ถ๋ฅผ ๋ ํด๋ด์ผ ํ๊ฒ ์ง๋ง, DOM์ ์ง์ ์ฐ๊ฒฐํ ์ ์๋๋ก ํด์ค๋ค๊ณ ํ๋ค. DOM์ ์ ๊ทผํด์ ๋ฌด์์ ์ป์ ์ ์๋์ง ๊ถ๊ธํ๋ค. ์ฐพ์๋ณด๋, ์ด๋ค ์ ๋ ฅ ํ๋์ ์๋์ผ๋ก ํฌ์ปค์ค๋ฅผ ๋ง์ถ๊ฑฐ๋, ์ด๋ค ์์์ ํฌ๊ธฐ ํน์ ์์น๋ฅผ ์์๋ด์ผ ํ ๋ ์ฌ์ฉํ ์ ์๋ค.
๋๋ ๋ฒํผ์ ๋ค์ ํด๋ฆญํ๊ฑฐ๋, ์ธ๋ถ ๋ฐํ์ ํด๋ฆญํ๋ฉด ๋๋กญ๋ฐ์ค๊ฐ ๋ซํ๊ฒ ํ๊ณ ์ถ์๋ค.
์ด ref๋ฅผ ์ฌ์ฉํ ์์ธํ ์ฝ๋๋ 2-2๊ฐ ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ถ๋ถ์์ ๋ ๋ค๋ฃฐ ์์ ์ด๋ค.
const toggleDropdown = () => {
setIsDropdownOpen(!isDropdownOpen);
};
์ด ์ฝ๋๋ ํจ์์ dropDown์ด ์ด๋ ค ์์ผ๋ฉด ๋ซ๊ณ , ๋ซํ์์ผ๋ฉด ์ด๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค.
์ด ํจ์๋ ์์ด์ฝ์ ํด๋ฆญํ์ ๋ ์คํํด์ผ ํ๋ค.
2-2. ์ด๋ฒคํธ ๋ฆฌ์ค๋
๋ค์์ผ๋ก ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
์์ ์ด์ง ์ธ๊ธํ๋ฏ์ด, ๋๋กญ๋ฐ์ค ์ธ๋ถ์ ์์ญ์ ํด๋ฆญํ๋ฉด ๋๋กญ๋ฐ์ค๊ฐ ๋ซํ๊ฒ ํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์ด๋ค.
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsDropdownOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
์ ๋ฆฌํ๋ฉด, ๋ฌด์ธ๊ฐ๋ฅผ ํด๋ฆญํ์ ๋ dropDown ์ธ๋ถ์ ๊ฒ์ธ์ง๋ฅผ ํ์ธํ๋ค. ๋ง์ฝ ์ธ๋ถ์ ๊ฒ์ด๋ผ๋ฉด
ref.current.contains(event.target) ๋ false๊ฐ ๋๋ค.
๊ทธ๋์ ์ธ๋ถ๋ผ๋ฉด, dropDown์ ๋ซ๊ฒ ๋๋ค.
3. ๋๋กญ๋ค์ด ๋ง๋ค๊ณ ์ฌ์ฉํ๊ธฐ
<DropdownContainer ref={ref}>
{/* ์์ด์ฝ ๋ฒํผ */}
<ProfileButton
onClick={toggleDropdown}
style={{ backgroundColor: "transparent" }}
>
{/* ์ฌ๊ธฐ์ ์ฌ์ฉํ ์์ด์ฝ์ ๋ฃ์ด์ค๋ค. */}
<AccountCircleIcon
sx={{
fontSize: "30px",
color: "white",
paddingTop: "5px",
paddingLeft: "20px",
paddingRight: "80px",
}}
/>
</ProfileButton>
{/* ๋๋กญ๋ฐ์ค๊ฐ ์ด๋ ค ์์ ๋ StyledDropdown ๋ณด์ฌ์ฃผ๊ธฐ */}
{isDropdownOpen && (
<StyledDropdown>
<ul style={{display: "flex", flexDirection: "column"}}>
<DropdownTextStyle href="/myPage">๋ด ๋ฒจ๋ก๊ทธ</DropdownTextStyle>
<DropdownTextStyle href="/notFound">์์ ๊ธ</DropdownTextStyle>
<DropdownTextStyle href="/notFound">์ฝ๊ธฐ ๋ชฉ๋ก</DropdownTextStyle>
<DropdownTextStyle href="/notFound">์ค์ </DropdownTextStyle>
<DropdownTextStyle href="/notFound">๋ก๊ทธ์์</DropdownTextStyle>
</ul>
</StyledDropdown>
)}
</DropdownContainer>
์ด๋ ๊ฒ ํ๋ฉด, ๋ด๊ฐ ์ํ๋ ๋๋กญ๋ค์ด ๋ฐ์ค๋ฅผ ์ง์ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค !!
๊ฒฐ๊ณผ
-> ํ๋กํ ์์ด์ฝ ์ ํํ์ ๋
-> ๋๋กญ๋ค์ด์ ์๋ ๋ฉ๋ด ํธ๋ฒ ์
'๐ฅ๏ธ react' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[react] ThemeProvider ์ฌ์ฉํ๊ธฐ (0) | 2024.01.20 |
---|---|
[react] react-dropdown ์ปค์คํ ํ๊ธฐ (0) | 2024.01.15 |
[react] markdown editor, viewer ๊ตฌํํ๊ธฐ (2) | 2023.01.29 |
[react] useEffect() (0) | 2022.12.27 |
styled components (0) | 2022.12.27 |