Styled Components with TypeScript
1. κ°μ
리μ‘νΈμμ μ€νμΌμ λ€λ£° λ styled-componentsλ₯Ό λ§μ΄ μ¬μ©νλ€. μ΄λ° styled-componentsκ³Ό Typescriptλ₯Ό ν¨κ» μ¬μ©νκΈ° μν΄μ μ΄λ»κ² ν΄μΌν κΉ? μ΄λ² μ±ν°μμλ ν΄λΉ λ΄μ©μ λ€λ£¬λ€.
2. declaration νμΌ μ€μΉ
$ npm i "styled-components"
μμ λͺ
λ Ήμ΄λ₯Ό ν΅ν΄ syled-componentsλ₯Ό μ€μΉνκ³ λ°λ‘ μ€νμΌμ λ€λ£¨κΈ° μν΄ μ¬μ©νλ€λ©΄ μλμ κ°μ μ€λ₯λ₯Ό λ°κ²¬νλ€.

μ΄λ₯Ό ν΄κ²°νκΈ° μν λ°©λ²μ μ€λ₯μμ μ°Ύμ μ μλ€. μλμ λͺ
λ Ήμ΄λ₯Ό μ
λ ₯νμ¬ styled-componentsμ κ΄λ ¨λ declarationνμΌμ μ€μΉνλ©΄ λλ€.
$ npm i --save-dev @types/styled-components
3. μ€νμΌ μ»΄ν¬λνΈμ μ¬μ©λλ propsμ νμ
μ νκΈ°
μλμ κ°μ μ»΄ν¬λνΈκ° μλ€κ³ μκ°νμ. Layoutμ μ€νμΌ μ»΄ν¬λνΈλ‘ isRed κ°μ μ λ¬ λ°μ μ°Έμ΄λ©΄ κΈμ¨μ μμ λΉ¨κ°μμΌλ‘ κ·Έλ μ§ μμΌλ©΄ νλμμΌλ‘ λνλΈλ€.
import React, { useState } from "react";
import styled from "styled-components";
const Layout = styled.div`
color: ${(props) => (props.isRed ? "red" : "blue")};
`;
const Box = ({ children }: React.PropsWithChildren) => {
const [isRed, setIsRed] = useState(true);
return (
<Layout isRed={isRed}>
<div>Box λΆλΆμ
λλ€.</div>
{children}
</Layout>
);
};
export default Box;Layoutλ μ€νμΌ μ»΄ν¬λνΈλ‘ κ·Όλ³Έμ μ»΄ν¬λνΈμ΄λ€. κ·Έλ κΈ° λλ¬Έμ propsλ₯Ό λΆλͺ¨ μ»΄ν¬λνΈμμ λ°μ μ¬μ©ν μ μλ€. μμ μμ μμλ isRedλΌλ propsλ₯Ό μ λ¬ λ°μ κ²½μ°μ΄λ€. νμ§λ§ μ λ¬λ§ νμ λΏ μ΄λ€ νμ
μ propsμΈμ§ μ μνμ§ μμ μ€λ₯κ° λ λͺ¨μ΅μ νμΈν μ μλ€.

κ·Έλ λ€λ©΄ Layoutμ props νμ
μ μ μνμ¬ μ€λ₯λ₯Ό ν΄κ²°νμ. λ¨Όμ Layout μ€νμΌ μ»΄ν¬λνΈ propμ νμ
μ μ μνλ©΄ μλμ κ°λ€.
interface IStyled {
isRed: boolean;
}κ·Έ λ€μ μ μν νμ
μ Layout μ€νμΌ μ»΄ν¬λνΈλ‘ μ λ¬νμ¬ Layout μ€νμΌ μ»΄ν¬λνΈμμ propsλ₯Ό μ¬μ©ν μ μλλ‘ νμ.
interface IStyled {
isRed: boolean;
}
const Layout = styled.div<Layout>`
color: ${(props) => (props.isRed ? "red" : "blue")};
`;4. μ€νμΌ μ»΄ν¬λνΈμ customMediaμμ propsκ° μ¬μ©λ λ
sytled componentsμ customMediaμ λ°μν λμμΈμ ν λ μ¬μ©λλ€. λΉμ°ν ν΄λΉ κΈ°λ₯μ μ¬μ©ν λλ μ€νμΌ μ»΄ν¬λνΈκ° propsλ‘ λ°μ λ³μλ₯Ό μ¬μ©ν μ μκΈ° λλ¬Έμ νμ
μ€ν¬λ¦½νΈλ₯Ό μ¬μ©νλ€λ©΄ λͺκ°μ§ μΆκ° μμ
μ ν΄μΌνλ€.
μ°Έκ³ λ‘ customMediaμ λ΄μ©μ μλμ κ°λ€.
import { generateMedia } from "styled-media-query";
export const customMedia = generateMedia({
mobile: "320px",
tablet: "768px",
desktop: "1024px",
});λ¨Όμ κΈ°μ‘΄ μλ°μ€ν¬λ¦½νΈμμλ μ΄λ»κ² μ¬μ©λλμ§ μμ보μ.
const SLunchmenu = styled.div`
display: grid;
${customMedia.greaterThan("tablet")`
row-gap: ${(props) => (props.summary ? "5px" : "10px")};
row-gap: ${(props) => (props.summary ? "0.3125rem" : "0.625rem")};
`}
`;SLunchmenu μ€νμΌ μ»΄ν¬λνΈ λ΄μ customMedia.greaterThan()μ μ¬μ©νμ¬ λ°μν λμμΈμ ν μ μλ€. μ΄λ customMedia.greaterThan()μμ μ¬μ©λλ propsλ μλμ λ°©λ²μΌλ‘ μ¬μ©ν μ μλ€.
${(props) => (props.summary ? "5px" : "10px")}κ·Έλ λ€λ©΄ νμ
μ€ν¬λ¦½νΈμ μ¬μ©νλ€λ©΄ μ΄λ»κ² λ κΉ? customMedia.greaterThan()κ° μλ μν©μμλ λ¨μ§ props νμ
λ§ μ μνλ©΄ λλ€. λ¨Όμ κ·Έλ κ² ν΄λ³΄μ.
interface IStyled {
summary?: string;
}
const SLunchmenu = styled.div<IStyled>`
display: grid;
${customMedia.greaterThan("tablet")`
row-gap: ${(props) => (props.summary ? "5px" : "10px")};
row-gap: ${(props) => (props.summary ? "0.3125rem" : "0.625rem")};
`}
`;IStyledλ‘ propsμ νμ
μ μ μνκ³ SLunchmenu μ€νμΌ μ»΄ν¬λνΈλ‘ μ λ¬νμλ€. νμ§λ§ μ΄λ κ²λ§ μμ±νλ©΄ μλμ κ°μ μ€λ₯λ₯Ό λ³Ό μ μλ€.

summaryκ° ThemeProps<any> νμ
μ μ‘΄μ¬νμ§ μλλ€λ μλ¬μ΄λ€. μ°λ¦¬λ IStyledμμ SLunchmenuμμ μ¬μ©νλ propsμ νμ
μ μ μλ₯Ό νλ€. νμ§λ§ μλ¬μ λ΄μ©μ 보면 νμ
μ΄ customMediaμ μ λλ‘ μ λ¬μ΄ λμ§ μμλ€λ κ²μ μ μ μλ€. κ·Έλ¬λ©΄ μ΄λ»κ² customMediaμ propsμ μ λ¬ν μ μμκΉ?
λ°©λ²μ μλμ κ°μ΄ μμ±νλ©΄ λλ€.
${({ summary }) => customMedia.greaterThan("tablet")`
row-gap: ${summary ? "5px" : "10px"};
row-gap: ${summary ? "0.3125rem" : "0.625rem"};
`}ν¨μλ‘ μ μνλ©΄ λλ€. summaryλ₯Ό λ€μ ν λ² λ μΈμλ‘ μ λ¬νλ©΄ customMediaμμ μ¬μ©ν μ μλλ‘ νλ€.
5. ThemeProviderμ theme νμ
ν΄λΉ λΆλΆμ ν°μ²μΊ 리ν©ν λ§μ μ§ννλ©΄μ λ€λ£¨κ² λ κ²½μ° μ 리νλ€.
π 2022-08-25 - 1. κ°μ ~ 4. μ€νμΌ μ»΄ν¬λνΈμ customMediaμμ propsκ° μ¬μ©λ λ
Last updated