개인 프로젝트로 리액트, 타입스크립트, Styled-components를 사용해 넷플릭스 웹사이트를 구현 중입니다.
메인 페이지 input 애니메이션을 구현하기 위해 컴포넌트에 props를 전달하는 순간...
타입스크립트 에러가 발생했습니다.
사전에 정의되지 않은 props 값을 전달했기 때문입니다.
에러를 해결하려면 해당 컴포넌트에 타입을 추가적으로 선언해야 했습니다.
👇🏻👇🏻 아래는 구현하려는 넷플릭스 메인 페이지의 input 애니메이션입니다. 👇🏻👇🏻
우선 구현하려는 애니메이션의 내용은 아래와 같습니다.
2번 상황을 정의한 이유는 input 태그를 focus하고 값을 입력하는 순간에는 '이메일 주소'가 의도한 대로 변하지만, input 태그를 제외한 다른 부분을 focus하는 순간 원 상태로 돌아와 입력한 값과 겹치는 문제가 발생하기 때문입니다.
1번 상황 문제 해결을 위해 focus 이벤트 관련 CSS 속성을 정의했습니다.
이제 input 태그를 focus하면 '이메일 주소' 텍스트가 원하는 대로 변화합니다.
const Input = styled.input`
...MORE STYLES...
&:focus {
outline: 1px solid #fff;
+ label {
top: 25%;
font-size: 0.5rem;
}
}
💁🏻 문제는 2번 상황에서 발생했습니다.
input 값을 상태로 관리하고 이를 Label 컴포넌트에 props로 전달해 길이가 0 이상이면 '이메일 주소' 텍스트의 스타일을 바꾸려고 했습니다.
하지만 Label 컴포넌트에 props를 전달한 순간 타입스크립트 에러가 발생했습니다.
문제를 해결하기 위해 Label 컴포넌트에 타입을 추가로 설정해야 했습니다.
전달하는 props의 개수가 1개 였기 때문에 다음과 같이 정의했습니다.
타입을 추가로 설정하고 나니 active 값의 유무에 따라 서로 다른 CSS 속성을 적용할 수 있게 됐습니다.
const Label = styled.label<{ active: string }>`
... MORE STYLES...
top: ${({ active }) => (active ? "25%" : "50%")};
font-size: ${({ active }) => (active ? "0.5rem" : "1rem")};
transform: translateY(-50%);
`;
👏🏻👏🏻 구현에 성공했습니다!!
컴포넌트에 전달하는 props의 개수에 따른 타입 선언 방법을 정리해보려고 합니다.
const ExampleComponent = styled.div<{ PROPS명: 타입 }>`
...MORE STYLES...
`;
코드 가독성을 위해 추가로 타입 혹은 인터페이스를 선언하면 됩니다.
interface IExampleComponent {
PROPS_1명: 타입1;
PROPS_2명: 타입2;
PROPS_3명: 타입3;
}
const ExampleComponent = styled.div<IExampleComponent>`
...MORE STYLES...
`;
기본적인 타입 선언 방법은 위와 동일합니다.
컴포넌트를 상속한다는 점만 다를 뿐입니다.
interface IChildComponent {
PROPS_1명: 타입1;
PROPS_2명: 타입2;
PROPS_3명: 타입3;
}
const ChildComponent = styled(상속 받을 컴포넌트명)<IChildComponent>`
...MORE STYLES...
`;