728x90
๋ฐ˜์‘ํ˜•
๋ฐ˜์‘ํ˜•

์ด์ „์— 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>

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฐ•์Šค๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค !!

 

๊ฒฐ๊ณผ

-> ํ”„๋กœํ•„ ์•„์ด์ฝ˜ ์„ ํƒํ–ˆ์„ ๋•Œ

 

-> ๋“œ๋กญ๋‹ค์šด์— ์žˆ๋Š” ๋ฉ”๋‰ด ํ˜ธ๋ฒ„ ์‹œ

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•

'๐Ÿ–ฅ๏ธ 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
728x90
๋ฐ˜์‘ํ˜•
๋ฐ˜์‘ํ˜•
728x90

react์—์„œ ๋“œ๋กญ๋ฐ•์Šค ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ

์–ด์ฉŒ๋‹ค ํ•˜๊ฒŒ ๋˜์—ˆ๋ƒ๋ฉด,

์ตœ๊ทผ ํ•™๊ต์—์„œ ๋ฐฉํ•™ ์ค‘ ์ง„ํ–‰ํ•˜๋Š” ์›น ์„œ๋น„์Šค ์บ ํ”„์— ์ฐธ์—ฌํ•˜๊ณ  ์žˆ๋‹ค.

๊ฐœ๋ฐœ ์–ธ์–ด, ํˆด ๋“ฑ์„ ์ž์œ ๋กญ๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ธฐ์— ๋‚˜๋Š” ํ”„๋ก ํŠธ๋Š” ๋ฆฌ์•กํŠธ๋กœ ๊ฐœ๋ฐœํ•˜๊ฒ ๋‹ค ๊ฒฐ์ •ํ•˜์˜€๋‹ค.

 

ํ˜„์žฌ ์ง์ ‘ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐํšํ•˜์—ฌ ์ƒˆ๋กœ์šด ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ , ์‹ค์ œ ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ํด๋ก ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋™์•„๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ธฐํš์˜ ๊ณผ์ •์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ ต๊ณ  ํž˜๋“ ์ง€๋ฅผ ์•Œ๊ณ  ์žˆ์—ˆ๊ธฐ์— ๋‚˜๋Š” ํด๋ก ์ฝ”๋”ฉ์„ ์„ ํƒํ•˜์˜€๋‹ค.

 

์ด๋ฒˆ ์บ ํ”„์—์„œ์˜ ๋ชฉํ‘œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

์›น ์„œ๋น„์Šค๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋Š” ์ „์ฒด์ ์ธ ๊ณผ์ •์„ ์ตํžˆ๋Š” ๊ฒƒ. (ํ”„๋ก ํŠธ๋ถ€ํ„ฐ ์„œ๋ฒ„๊นŒ์ง€)

 

์ด๋ฅผ ์œ„ํ•ด Velog๋ฅผ ํด๋ก ์ฝ”๋”ฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜์˜€๋‹ค.

 

์„œ๋ก ์ด ๊ธธ์—ˆ๋Š”๋ฐ, ํด๋ก ์ฝ”๋”ฉ์„ ํ•˜๋‹ค๋ณด๋‹ˆ ๋“œ๋กญ๋ฐ•์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ์ผ์ด ์žˆ์—ˆ๋‹ค.

์‚ฌ์šฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋””์ž์ธ๋„ ์ปค์Šคํ…€ํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ–ˆ๋‹ค.

 

 

1. react-dropdown ์„ค์น˜ํ•˜๊ธฐ

 

ํ„ฐ๋ฏธ๋„์— ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์ค€๋‹ค.

// npm์œผ๋กœ ์„ค์น˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.
$ npm install react-dropdown

// yarn์œผ๋กœ ์„ค์น˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค.
$ yarn add react-dropdown

https://www.npmjs.com/package/react-dropdown

 

react-dropdown

React dropdown component. Latest version: 1.11.0, last published: a year ago. Start using react-dropdown in your project by running `npm i react-dropdown`. There are 148 other projects in the npm registry using react-dropdown.

www.npmjs.com

( ์ž์„ธํžˆ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ์œ„ ์‚ฌ์ดํŠธ ์ฐธ๊ณ ํ•˜๊ธฐ )

 

 

2. ์ƒ๋‹จ์— import ํ•ด์ฃผ๊ธฐ

 

์„ค์น˜๊ฐ€ ์™„๋ฃŒ ๋˜์—ˆ๋‹ค๋ฉด, ํŒŒ์ผ ์ƒ๋‹จ์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ import ํ•ด์ค€๋‹ค.

์„ค์น˜๊ฐ€ ์ž˜ ๋˜์—ˆ๋‹ค๋ฉด, ์•„๋ฌด๋Ÿฐ ์—๋Ÿฌ ์—†์ด import๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

import Dropdown from 'react-dropdown';
import "react-dropdown/style.css";

๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ import ํ•ด์ค˜์•ผ ํ•œ๋‹ค !

 

์ด๋ ‡๊ฒŒ import๊ฐ€ ์ž˜ ๋˜์—ˆ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

const options = [
  'one', 'two', 'three'
];
const defaultOption = options[0];
<Dropdown options={options} onChange={this._onSelect} value={defaultOption} placeholder="Select an option" />;

(์œ„ ์ฝ”๋“œ๋Š” ๊ณต์‹ ๋ฌธ์„œ์— ๋‚˜์˜จ ์˜ˆ์ œ์ด๋‹ค !)

 

 

3. ์ปค์Šคํ…€ ํ•˜๊ธฐ !!

์œ„ ์ด๋ฏธ์ง€๋Š” ๋‚ด๊ฐ€ ์ปค์Šคํ…€ํ•ด์„œ ๋งŒ๋“  ๊ฒฐ๊ณผ๋ฌผ์ด๋‹ค.

 

์ปค์Šคํ…€์„ ํ•˜์ง€ ์•Š์œผ๋ฉด, ๊ธฐ๋ณธ ๋””์ž์ธ์œผ๋กœ ๋ณด์—ฌ์ง„๋‹ค.

๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปค์Šคํ…€ ํ•˜์˜€๋Š”์ง€ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž !!

 

 

3-1. ๋“œ๋กญ๋ฐ•์Šค ์ž์ฒด๋ฅผ ์ปค์Šคํ…€ํ•˜๋ ค๋ฉด,

 

์—ฌ๊ธฐ์—์„œ ๋“œ๋กญ๋ฐ•์Šค ์ž์ฒด๋ž€, ์•„๋ž˜์™€ ๊ฐ™์€ ์ด๋ฏธ์ง€์ด๋‹ค. ์ฆ‰, ๋ฐ•์Šค๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š์€, ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ๋ณด์—ฌ์ง€๋Š” ๋ถ€๋ถ„์ด๋‹ค.

ํ˜„์žฌ ๋‚ด๊ฐ€ ์ค€ ์ปค์Šคํ…€์€, ๋ฐฐ๊ฒฝ์ƒ‰, ํฐํŠธ ํฌ๊ธฐ, ๋ฐ•์Šค border-radius, ๋†’์ด, ๋„ˆ๋น„๊ฐ€ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์†์„ฑ๋“ค์„ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋œ๋‹ค.

์•— ์ฐธ๊ณ ๋กœ ๋‚˜๋Š” styled component๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

const StyledDropdown = styled(Dropdown)`
  .Dropdown-control {
    background-color: ${theme.colors.secondBlack};
    color: white;
    border-radius: 5px;
    border-color: transparent;
    width: 110px;
    height: 32px;
    font-size: 13px;
  }
`;

์ด๋ ‡๊ฒŒ .Dropdown-control์„ ๊ฐ€์ ธ์™€ ํ•ด๋‹น ์†์„ฑ์— ์ ‘๊ทผํ•ด ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

 

 

3-2. ๋“œ๋กญ๋ฐ•์Šค๋ฅผ ์—ด์—ˆ์„ ๋•Œ ๋ณด์—ฌ์ง€๋Š” ๋ฉ”๋‰ด๋ฅผ ์ปค์Šคํ…€ ํ•˜๋ ค๋ฉด,

 

๋“œ๋กญ๋ฐ•์Šค๋ฅผ ํด๋ฆญํ•˜์—ฌ ์—ด๋ฆฌ๋Š” ๋ฉ”๋‰ด๋“ค์„ ์ปค์Šคํ…€ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

 

์ด๋ ‡๊ฒŒ ๋‚˜๋Š” ๋ฉ”๋‰ด์˜ ๋ฐฐ๊ฒฝ ์ƒ‰, ํฐํŠธ ํฌ๊ธฐ, ํฐํŠธ ์ƒ‰ ๋“ฑ์„ ์ง€์ •ํ•˜์˜€๋‹ค.

๋“œ๋กญ๋ฐ•์Šค ๋ฉ”๋‰ด๋ฅผ ์ปค์Šคํ…€ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜๋ฉด ๋œ๋‹ค.

.Dropdown-menu {
    background-color: ${theme.colors.secondBlack};
    color: white;
    font-size: 13px;
  }

์ด๋ ‡๊ฒŒ .Dropdown-menu์— ์ ‘๊ทผํ•˜์—ฌ ํ•ด๋‹น ์†์„ฑ๋“ค์„ ์ปค์Šคํ…€ํ•˜๋ฉด ๋œ๋‹ค.

 

 

3-3. ์„ ํƒ๋œ ์˜ต์…˜์„ ์ปค์Šคํ…€ํ•˜๋ ค๋ฉด,

 

๋‚ด๊ฐ€ ์„ ํƒํ•œ ์˜ต์…˜์€ ๋‹ค๋ฅด๊ฒŒ ๋ณด์—ฌ์ ธ์•ผ ํ•œ๋‹ค. 3-2์—์„œ์˜ ์‚ฌ์ง„์„ ๋ณด๋ฉด, ๋‚ด๊ฐ€ ์„ ํƒํ•œ '์ด๋ฒˆ ์ฃผ'๋Š” ์ƒ‰์ƒ์ด ๋‹ค๋ฅด๊ฒŒ ํ‘œ์‹œ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ฒ˜๋Ÿผ ์„ ํƒํ•œ ์˜ต์…˜์— ๋Œ€ํ•œ ์†์„ฑ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋œ๋‹ค.

.Dropdown-option.is-selected {
    color: ${theme.colors.primary};
    background-color: ${theme.colors.secondBlack};
    font-size: 13px;
  }

์ด๋ ‡๊ฒŒ .Dropdown-option.is-selected์— ์ ‘๊ทผํ•˜์—ฌ ์„ ํƒํ•œ ์˜ต์…˜์— ๋Œ€ํ•œ ๋””์ž์ธ์„ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

3-4. ๋งˆ์ง€๋ง‰์œผ๋กœ, ๋‚˜๋จธ์ง€ ์˜ต์…˜๋“ค์„ ์ปค์Šคํ…€ํ•˜๋ ค๋ฉด,

์ด ๋ถ€๋ถ„์€ 3-2 ๋ถ€๋ถ„์—์„œ ์ด๋ฏธ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค ์ƒ๊ฐํ–ˆ์œผ๋‚˜, ๋”ฐ๋กœ ๋˜ ํ•ด์ค˜์•ผ ์ ์šฉ์ด ๋˜์—ˆ๋‹ค.

3-2, 3-4 ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์ฃผ์„์ฒ˜๋ฆฌํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋œ๋‹ค..

์„ ํƒ๋œ ์˜ต์…˜์ด ์•„๋‹Œ ๋‚˜๋จธ์ง€ ์˜ต์…˜๋“ค์„ ์ปค์Šคํ…€ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜์˜€๋‹ค.

.Dropdown-option {
    color: ${theme.colors.white};
    font-size: 13px;
  }

์ด๋ ‡๊ฒŒ .Dropdown-option์— ์ ‘๊ทผํ•˜์—ฌ ํ•ด๋‹น ์†์„ฑ๋“ค์„ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

 

 

4. ์ •๋ฆฌํ•˜๋ฉด,

 

์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‚˜๋Š” styled component๋ฅผ ์‚ฌ์šฉํ•˜์˜€๊ธฐ์— ์ด๋ ‡๊ฒŒ ๋ฐฑํ‹ฑ ์•ˆ์— ๋„ฃ์–ด์ฃผ์—ˆ๋‹ค.

const StyledDropdown = styled(Dropdown)`
  .Dropdown-control {
    background-color: ${theme.colors.secondBlack};
    color: white;
    border-radius: 5px;
    border-color: transparent;
    width: 110px;
    height: 32px;
    font-size: 13px;
  }
  .Dropdown-menu {
    background-color: ${theme.colors.secondBlack};
    color: white;
    font-size: 13px;
  }
  .Dropdown-option.is-selected {
    color: ${theme.colors.primary};
    background-color: ${theme.colors.secondBlack};
    font-size: 13px;
  }
  .Dropdown-option {
    color: ${theme.colors.white};
    font-size: 13px;
  }
`;

์‹ค์ œ ์ด ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.

<StyledDropdown options={options} value={defaultOption} />

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณตํ•ด์ฃผ๋Š” dropdown์„ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋””์ž์ธ๋Œ€๋กœ ์ปค์Šคํ…€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•
#colorLiteral(

๊นŒ์ง€ ์ž…๋ ฅํ•˜๋ฉด, ์‚ฌ๊ฐํ˜•์ด ์ƒ๊ธฐ๋Š”๋ฐ, ์ด ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜๋ฉด ์ƒ‰์ƒ ํŒ”๋ ˆํŠธ๊ฐ€ ์—ด๋ฆฌ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ์›ํ•˜๋Š” ์ƒ‰์ƒ์„ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค !

 

์ง€๊ธˆ๊นŒ์ง€ ๋‚ด์žฅ๋ผ ์žˆ๋Š” ์ƒ‰์ƒ๋“ค์„ . ์„ ๋ˆŒ๋Ÿฌ ํ•œ์ •์ ์œผ๋กœ ์„ ํƒํ–ˆ์—ˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ์‰ฝ๊ฒŒ ์˜ˆ์œ ์ƒ‰๋“ค์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ๊ฐœ๋ฐœ์„ ์กฐ๊ธˆ ๋” ์žฌ๋ฐŒ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค ใ…Žใ…Ž

 

์•„์ฃผ์•„์ฃผ ์ข‹์€ ๊ฟ€ํŒ ๐Ÿฏ

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•

์•ฑ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด Simulator์—์„œ ๋‹คํฌ๋ชจ๋“œ, ๋ผ์ดํŠธ ๋ชจ๋“œ๋ฅผ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ํ™•์ธ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

์ด๋•Œ, ๋งค๋ฒˆ ์„ค์ •์— ๋“ค์–ด๊ฐ€์„œ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด๋„ˆ๋ฌด๋„ˆ๋ฌด ๋น„ํšจ์œจ์ ์ด๋‹ค...

 

์•„์ฃผ ๊ฐ„๋‹จํ•œ ๋‹จ์ถ•ํ‚ค๋กœ ์‰ฝ๊ฒŒ ๋ชจ๋“œ์ „ํ™˜์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋‹ˆ !!

 

command + shift + a

๋‹จ์ถ•ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์•„์ฃผ ์‰ฝ๊ฒŒ ๋ชจ๋“œ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค !!

 

๊ฒฐ๊ณผ ์˜ˆ์‹œ

๋‹คํฌ๋ชจ๋“œ
๋ผ์ดํŠธ๋ชจ๋“œ

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•
๋ฐ˜์‘ํ˜•

 

๋ฐ˜์‘ํ˜•

 

์ตœ๊ทผ ์ง„ํ–‰ ์ค‘์ธ ํ”„๋กœ์ ํŠธ์—์„œ swift data๋ฅผ ์‚ฌ์šฉํ• ์ง€, realm์„ ์‚ฌ์šฉํ• ์ง€ ๊ณ ๋ฏผํ•ด์˜ค๊ธฐ๋กœ ํ–ˆ๋‹ค.

swift์— ์ž…๋ฌธํ•œ์ง€ ์–ผ๋งˆ ๋˜์ง€ ์•Š์€ ๋‚˜๋Š” ์‚ฌ์‹ค ๋‘˜ ๋‹ค ์ž˜ ๋ชจ๋ฅธ๋‹ค...

swift Data์— ๋Œ€ํ•œ ๊ณต์‹ ๋ฌธ์„œ์„ ์งง๊ฒŒ ํ•œ๊ตญ์–ด๋กœ, ๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”๋ฅผ ํ’€์–ด์„œ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

์‹œ์ž‘!

 

๋ฐ˜์‘ํ˜•

 

๐ŸŽ Swift Data

swiftData๋Š” ์„ ์–ธํ˜• ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ data๋ฅผ ์‰ฝ๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

์šฐ๋ฆฌ๋Š” swift ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ data๋ฅผ query๋ฅผ ์‚ฌ์šฉ, filterํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๋Š” swiftUi์™€ ์›ํ™œํ•˜๊ฒŒ ํ†ตํ•ฉ๋˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

 

๋ฐ˜์‘ํ˜•

 

๐ŸŽ swift๋กœ ๋ชจ๋ธ ์ƒ์„ฑํ•˜๊ธฐ

์ถ”๊ฐ€๋กœ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜, ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ tool์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ @Model ์„ ์‚ฌ์šฉํ•ด์„œ data๋ฅผ ๊ตฌ์กฐํ™” ํ•˜๊ณ  ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

swiftData๋Š” ์ž๋™์œผ๋กœ ๋งŽ์€ ๊ด€๊ณ„๋“ค์„ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ์šฐ๋ฆฌ๋Š” @Attribute(.unique)์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ์„ ์–ธ์„ ํ†ตํ•ด ์ œ์•ฝ๋“ค์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ SwiftUI์—์„œ ์ด๋ฅผ ์ ์šฉํ•œ ์ฝ”๋“œ ์˜ˆ์‹œ์ด๋‹ค.

@Model
class Recipe {
	@Attribute(.unique) var name: String
	var summary: String?
	var ingredients: [Ingredient]
}

 

๋ฐ˜์‘ํ˜•

๐ŸŽ Automatic persistence

swiftData๋Š” ์šฐ๋ฆฌ์˜ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•ด์„œ ์‚ฌ์šฉ์ž ์ •์˜ ์Šคํ‚ค๋งˆ๋ฅผ ๊ตฌ์ถ•ํ•ด์ฃผ๊ณ , ํ•ด๋‹น ๋ชจ๋ธ์˜ fields๋ฅผ ๊ธฐ๋ฐ˜ ์Šคํ† ๋ฆฌ์ง€์— ํšจ์œจ์ ์œผ๋กœ ๋งคํ•‘ํ•ด์ค€๋‹ค.

์ฆ‰, ๋ชจ๋ธ์˜ ํ•„๋“œ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ์—ด๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ!

swiftData๋กœ ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด๋“ค์€ ํ•„์š”ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ถ”๊ฐ€์ ์ธ ์ž‘์—… ์—†์ด ์›ํ•˜๋Š” ์ ์ ˆํ•œ ์‹œ์ ์— ์ž๋™์œผ๋กœ ์ €์žฅ๋œ๋‹ค. ๋˜ํ•œ, ModelContext API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์ฒด์ ์ธ ์ œ์–ด๋ฅผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

๋ฐ˜์‘ํ˜•

 

๐ŸŽ Integrates with SwiftUI

SwiftUI view์—์„œ @Query๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

SwiftData์™€ SwiftUI๋Š” ํ•จ๊ป˜ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์ˆ˜๋™์œผ๋กœ ์ƒˆ๋กœ๊ณ ์นจ์„ ํ•˜์ง€ ์•Š์•„๋„ ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ ๋œ๋‹ค.

@Query var recipes: [Recipe]
var body: some View {
	List(recipes) { recipe in
		NavigationLink(recipe.name, destination: RecipeView(recipe))
	}
}
๋ฐ˜์‘ํ˜•

 

๐ŸŽ Swift-native predicates

์ปดํŒŒ์ผ๋Ÿฌ์— ์˜ํ•ด ๊ฒ€์‚ฌํ•œ ํŠน์ • ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•˜๊ณ , ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ๊ฐœ๋ฐœ ์ค‘ ์ƒ๊ธฐ๋Š” ์˜คํƒ€์™€ ์‹ค์ˆ˜๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

let simpleFood = #Predicate<Recipe> { recipe in
	recipe.ingredients.count < 3
}
๋ฐ˜์‘ํ˜•

 

๐ŸŽ CloudKit syncing

ClounKit์™€ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋ฐ˜์‘ํ˜•

 

๐ŸŽ Compatible with Core Data

๊ธฐ์กด์— core data๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœํ–ˆ๋‹ค๋ฉด, swift data๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

์–ผ๋ฅธ ํ•œ ๋ฒˆ ์จ๋ณด๊ณ  ์‹ถ๋‹ค !

์ฐธ๊ณ  ๋ฌธ์„œ : https://developer.apple.com/xcode/swiftdata/

 

SwiftUI Overview - Xcode - Apple Developer

SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift.

developer.apple.com

 

728x90
๋ฐ˜์‘ํ˜•

 

 

728x90
๋ฐ˜์‘ํ˜•

 

728x90
๋ฐ˜์‘ํ˜•

+ Recent posts