- Published on
๐ ์ปฌ๋ฌ๋ฆฌ์คํธ ํ๋ก์ ํธ #17 button ์ปดํฌ๋ํธ ๋ถ๋ฆฌ - ๋์์ธ ์์คํ
- ๊ธ์ด์ด
๐
์ค๋์ ํ์ฌ ํ๋ก์ ํธ์ ์ค๋ณตํด์ ๋ณด์ด๋ ๋ฒํผ์ ๋์์ธ ์์คํ ์ฒ๋ผ ๋ฐ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํด ๊ฐ๊ฐ์ ํ์ ๊ณผ ํด๋์ค๋ค์์ ๋ง๊ฒ ๋ณํํ ์ ์๋๋ก ํด๋ณด์๋ค. ๋ํ ์ ๋๋ฆญ์ ์ฌ์ฉํด ๋ค๋ฅธ ํ๊ทธ์๋ ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก ๋คํ์ ์ธ ์ปดํฌ๋ํธ๊น์ง ์๋ํด๋ณด์๋ค.
๋ฒํผ ์ปดํฌ๋ํธ ๋ถ๋ฆฌ
ํ
์คํธ ํผ์ ํ๋จ ์ ์ฅํ๊ธฐ ๋ฒํผ์ ๊ธฐ์ค์ผ๋ก ์ผ์์ ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํ๋ค.
๋ถ๋ฆฌํ๋ ์ด์ ๋ ๋์์ธ ์์คํ
์ ์ฌ์ฉํ๋ ์ด์ ์ ๊ฐ์๋ฐ,
์ค๋ณต๋๋ ๋ฒํผ๋ค์ ํ๋ฒ์ ์์ ํ๊ธฐ๊ฐ ์ฌ์์ง๊ณ , ์ผ๊ด์ฑ ์๋ ํ๋ฉด์ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
1๋จ๊ณ ๊ธฐ์กด ํ๋ฉด์์ ํน์ ํ ๋ถ๋ถ์ ์๋ผ์, Button.tsx ๋ก ๋ถ๋ฆฌํ๋ค
import React from 'react'
function Button() {
return (
<button type="submit" className="bg-yellow-300 p-4 rounded-xl">
์ ์ฅํ๊ธฐ
</button>
)
}
export default Button
2๋จ๊ณ props๋ก ๋ฐ๋๋ ๋ถ๋ถ์ ๋ฐ๊ธฐ - ์ถ์ถํ ๋๋ ๋ณํ๋ ๋ถ๋ถ๊ณผ ๋ณํ์ง ์์ ๋ถ๋ถ์ ๊ตฌ๋ถํด์ผ
import React from 'react'
// "string" => string literal type => ์์๊ฐ 1๊ฐ์ธ ์งํฉ
// string => ๋ชจ๋ ๊ฐ๋ฅํ ๋ฌธ์์ด๋ค์ ํ์
=> ์์๊ฐ ๋งค์ฐ ๋ง์ ์งํฉ!
function Button({ type, children }: { type: 'submit' | 'button'; children: string }) {
return (
<button type={type} className="bg-yellow-300 p-4 rounded-xl">
{children}
</button>
)
}
export default Button
3๋จ๊ณ type์ ๊ฐ์ํํ๊ณ , className์ ์ถ๊ฐํ ์ ์๊ฒ ๋ง๋ค๊ธฐ
React component
๋ก์จ button
์ด ๊ฐ์ง ์ ์๋ ๋ชจ๋ props
๋ฅผ ๋๊ฒจ์ค์ผ๋ก์จ
type
์ ํ๋ํ๋ ์ง์ ํด์ฃผ์ง ์์๋ ๊ฐ๋จํ๊ฒ ๋ชจ๋ props
๋ฅผ ๋ฐ์ ์ ์๋ button
์ ๋ง๋ค ์ ์๋ค.
className
์ props
์ ๋ฃ์ด์ฃผ์ด ๊ฐ ํ์ด์ง์์ ์ถ๊ฐ๋ก ํ์ํ className
(tailwind๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ className
์
์ด์ฉํด css๋ฅผ ์์ ํ๋ค.)์ ๋ฃ์ ์ ์๋๋ก ํ๋ค.
import React from 'react'
type ButtonProps = React.ComponentProps<'button'> // <- ์ค์!
function Button({ type, children, className }: ButtonProps) {
return (
<button type={type} className={'bg-yellow-300 p-4 rounded-xl ' + className}>
{children}
</button>
)
}
export default Button
4๋จ๊ณ polymorphic component (๋คํ์ ์ธ ์ปดํฌ๋ํธ)
๊ฐ์ ๋์์ธ ์์คํ
์ปดํฌ๋ํธ๋ฅผ... ์๋ก ๋ค๋ฅธ ํ๊ทธ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํด์ค!
"๋ ๋ง์ ์ฌ์ฉ๋ก๋ฅผ ์ง์ํ๋ ค๋ฉด ๋ ๋ณต์กํ๊ฑฐ๋, ๋จ์ํ๋๋ผ๋ ๋ ์ดํดํ๊ธฐ ์ด๋ ค์ด ๊ฐ๋
์ด ํ์ํ๋ค"
์ ๋ค๋ฆญ์... ํ์ ์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ์ ์๋ค. C๋ก ๋ญ ๋ฐ๋๋์ ๋ฐ๋ผ์ "button"๋ ์ด์ ๊ฐ๋ฅํ๊ณ "a"๋ ๊ฐ๋ฅ!
-
์คํ๋ ๋ ์ฐ์ฐ์๋ก ๊ตฌ์กฐ๋ถํดํ ๋น๋ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๊ธฐ
-
์คํ๋ ๋ ์ฐ์ฐ์๋ก react component์ props๋ฅผ ๋๊ธฐ๊ธฐ
import React from 'react'
type ButtonProps<C extends React.ElementType = 'button'> = React.ComponentProps<C> & {
as?: C
className: string
children: React.ReactElement
}
function Button<C extends React.ElementType>({
as,
className,
children,
...props // as, className, children์ ์ ์ธํ ๋๋จธ์ง props๋ props ๊ฐ์ฒด๋ก ๋ฐ๋๋ค
}: ButtonProps<C>) {
const Component = as || 'button'
return (
<Component
className={
'bg-yellow-300 hover:bg-yellow-400 transition-colors duration-200 p-4 rounded-xl ' +
className
}
{...props} // props ๊ฐ์ฒด์ ์๋ ๋ชจ๋ prop์ Component์ ๋๊ธด๋ค
>
{children}
</Component>
)
}
export default Button
๋์์ธ ์์คํ
๋ง๋๋ ์ด์
๋์์ธ์ ํต์ผ์ฑ!, ๊ณตํต๋๋ ๋ก์ง์ ์ฌ์ฌ์ฉํด์ ์์ฐ์ฑ๋ ๋์ด๊ณ , ๋ณ๊ฒฝ ์ฌํญ๋ ๋ฐ์ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ฌ(์ ์ง๋ณด์์ฑ)
๋ง๋๋ ๋ฐฉ๋ฒ
์ํฅ์ => ๊ทธ๋ฅ ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ ๋น์ทํด ๋ณด์ด๋ ์ปดํฌ๋ํธ๋ค์ ๋ฌถ์ด์ ์ถ์ถํด๋๊ฐ๋ค (์ด๊ธฐ!)
ํํฅ์ => ํ์ฌ ๊ท๋ชจ๋ ํฌ๊ณ , ์๋๋ฉด ์ฒ์๋ถํฐ ์ฒด๊ณ๋ฅผ ๊ฐ์ถ๊ณ ์ถ๊ณ , ๊ธฐ์กด์ ๋ฒ ์คํธ ํ๋ํฐ์ค๋ ์ดํด๋๊ฐ ๋์ ๋!
์ง๊ธ ๋์ ๊ฐ์ ๊ฒฝ์ฐ๋, ํ ์ดํ๋ก์ ํธ๋ก ์์ฃผ ์์ ๊ท๋ชจ์ด๋ฏ๋ก ์ํฅ์์ผ๋ก ๋ง๋ ๋ค.
css reset์ ํ๋ ์ด์
-
๋ธ๋ผ์ฐ์ ๋ง๋ค ๊ธฐ๋ณธ CSS๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์์ CSS๋ฅผ ์ด๊ธฐํ์์ผ๋๊ณ ์ฒ์๋ถํฐ ๋ชจ๋ ๋๊ฐ์ ํ๋ฉด์ ๋ณผ ์ ์๋๋ก ๋ง๋ ๋ค.
-
semantic๊ณผ ์๊ฐ์ ํํ๋ ๋ถ๋ฆฌ๋์ด์ผ ํ๋ค
variant
๊ฐ์ ์ฉ๋์ฌ๋ ์๊ฐ์ ์ฐจ์ด๊ฐ ์์๋๋ variant๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
ํจ์์์์ variant
์ ํท๊ฐ๋ฆฌ์ง ๋ง ๊ฒ.
๋ฐ์ํ UI์ tailwind
tailwind
์์ ์ฌ์ฉํ๋ class
๋ฅผ "utility class"๋ผ๊ณ ํ๋ค.
css
์ ๋ค๋ฅด์ง ์๋ค! className
์ ์ฐ๋ ๊ฒ ๋ค๋ฅผ ๋ฟ~
clsx
=> className
์ ์ฌ๋ฌ ๊ฐ๋ก ์ชผ๊ฐ์ ๊ตฌ๋ถํด์ ๊ด๋ฆฌํ ์ ์์