ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Styled-Component에서는 id props를 사용할 수 없나요?
    Studying/React 2023. 6. 27. 23:58

    문제 발생

     

    [Pre-Project] 위젯, 로그인, 회원가입 UI 구현하기

    들어가면서... Pre-Project를 통해 Stack Overflow 웹사이트를 클론 코딩 하게 되었습니다. 여태껏 써보지 않았던 라이브러리, TypeScript 등 꽤 많은 도전이 있어서 그 기록을 남기려고 합니다. styled-componet

    all-done.tistory.com

     

    Stack-Overflow 홈페이지 클론 코딩 중, 오른쪽 사이드 바 UI를 구현하던 중 styled-component의 id props가 인식되지 않았습니다.

     

     

    Widget 컴포넌트는 아래와 같이 WidgetProps를 인자로 받아 위젯을 생성합니다.

    const Widget = ({id, type, isstuck, title, children}:WidgetProps) => {
        return(
            <WidgetContainer type={type} id={id} isstuck={isstuck}>
                <WidgetHeader type={type}>{title}</WidgetHeader>
                {children}
            </WidgetContainer>
        )
    }

    여기서 <WidgetContainer> 가 바로 문제를 발생시키는 Styled-Component 입니다.

     

    <WidgetContainer>는 type, id, isstuck 세 가지 인자를 받습니다.

     

    그 중 id 인자는 Widget이 map으로 호출될 경우 몇 번째 위젯인지 알기 위해 사용됩니다.

    const WidgetContainer = styled.div<{type:string|undefined, id:number, isstuck:boolean|undefined}>`
        border-radius: ${props.id !== 1 && '0'};
        border-top: ${props.id !== 1 && '0px'};
    `

     

    그런데 여기서 문제가 발생했습니다.

     

    <WidgetContainer>id props에 다음과 같은 에러가 발생했습니다.

     

    (property) id : never 이 호출과 일치하는 오버로드가 없습니다. 오버로드 1/2(
    '(props: { slot?: string; style?: CSSProperties; title?: string; ref?: Ref<HTMLDivElement>; key?: Key; defaultChecked?: boolean; defaultValue?: string | number | readonly string[]; ... 257 more ...; isstuck: boolean; } & Partial<...> & { ...; } & { ...; }): ReactElement<...>'
    )에서 다음 오류가 발생했습니다.
    'number' 형식은 'never' 형식에 할당할 수 없습니다. 오버로드 2/2(
    '(props: StyledComponentPropsWithAs<"web", "div", { type: string; id: number; isstuck: boolean; }, never, "div">): ReactElement<StyledComponentPropsWithAs<"web", "div", { type: string; id: number; isstuck: boolean; }, never, "div">, string | JSXElementConstructor<...>>'
    )에서 다음 오류가 발생했습니다.

     

    id 에 대한 타입을 number로 명시해 주었는데 왜 never 형식이라는 것일까요?

     

     

     

    Styled-Component에서는 id props를 사용할 수 없다?

    저 에러를 처음 마주했을 때 가장 먼저 never 타입이 무엇인지 알아보았습니다.

     

    never 타입이란, 어떤 값도 가질 수 없는 값 입니다.

     

    🎁 never 타입에 관한 원문 번역 1)

    🎁 never 타입에 관한 원문 번역 2)

    (아래 두 블로그 모두 동일한 원문을 번역한 것 같으나, 설명의 디테일이 달라서 둘 다 읽어보는 것도 좋을 것 같습니다.)

     

    id 는 이런 타입을 가지는 걸까요?

     

    원인은 아래 주소에서 찾아볼 수 있었습니다.

     

     

    The component styled.div with the id of "sc-fzqAui" has been created dynamically. You may see this warning because you've called

    The component styled.div with the id of "sc-fzqAui" has been created dynamically. You may see this warning because you've called styled inside another component. To resolve this only create new Sty...

    github.com

     

    저와 동일한 문제에 대한 질문글은 아닌데요,

     

    The component styled.div with the id of "sc-fzqAui" has been created dynamically.

     

     

    라는 부분에서 해답을 찾을 수 있었습니다.

     

    게시자 분이 생성한 id="sc-fzqAui" 인 styled.div가 동적으로 생성된다는 에러가 발생한 것입니다.

     

    여기서 다음 특징을 바로 알 수 있었습니다.

     

    styled-component는 자동으로 string 타입의 id가 props로 생성된다.

     

    저 또한 함수형 컴포넌트 안에 styled-component를 정의해서 dynamically 호출에 대한 에러를 받았었는데요, 그때 id 라는 것에 크게 초점을 두지 않아서 id 자동 생성에 대해서는 알 수 없었습니다.

     

    생각해보면 styled-component를 개발자 도구로 클릭 해보았을 때 아래와 같이 class 가 자동 생성되는 건 알고 있었습니다. 그래서 id 로 구분되지 않고 오직 class로만 styled-component가 구분되어 생성되는 줄 알았습니다.

     

     

    이 부분에 대해서는 어째서 개발자 도구로 클릭했을 땐 id 가 나오지 않는지 알아내지 못 했습니다.

     

    그 대신 자동으로 string 타입의 id가 props로 생성된다. 라는 것에 대해서는 아래와 같이 증명할 수 있었습니다.

     

    const WidgetContainer = styled.div<{type:string|undefined, isstuck:boolean|undefined}>`
        border-radius: ${props.id !== "1" && '0'};
        border-top: ${props.id !== "1" && '0px'};
    `

     

    이렇게 props로 정의하지 않는 id를 string 타입으로 사용해도 아무런 에러가 발생하지 않는다는 점 입니다.

     

    다만 id 값은 제가 원하는 string이 될 수 없으니 조건부 CSS를 적용할 수 없겠지만요. 당장 에러만 나지 않는다는 걸 보아 정의하지 않는 id 값을 가지는 건 확실한가 봅니다.

     

    이는 id 뿐만 아니라 key, title, style 과 같은 기본 속성들에 대해서도 동일한 것 같습니다. 정의하지 않은 key, title, style props 또한 string 타입으로 사용하는 것에 아무런 에러가 나타나지 않네요.

    └▷ 그런데 우리가 주로 '기본 속성' 이라고 하는 모든 속성에 대해서 string 값을 자동으로 생성하는 건 아닙니다.(ref, class 등은 안 됨)

     

    제가 경험한 바 key는 굳이 styled-component가 아닌 map으로 호출한 React Component에서도 unique key값은 props로 인식이 안 됩니다. 그래서 동일한 unique 값을 id props로 넘겨줘 사용했던 기억이 납니다. 그와 같은 원리인지는 모르겠습니다.

     

    그럼 위에서 본 화면 캡쳐에서 자동으로 생성된 class 이름이 id 값으로도 생성되는지 문득 궁금해졌습니다.

     

    background-color: ${(props)=>props.id === 'sc-iUXMdM' && '#780404'};

     

    그래서 특정 styled.div 의 class를 따와 조건이 참인지 확인해 봤지만 다른가보네요. 애초에 never 타입이라고 하였으니 정말 아무런 값이 없어야 하는 거 아닌가 싶은데 string 타입은 또 가능하고, 이것저것 앞뒤가 맞지 않는 것 같네요. 더 정확한 이유를 알고싶으나 지금은 일단 알게 된 것만 적어봅니다.

     

    그러면, string 타입의 id를 자동 생성한다고 했으니까 string 타입의 값을 id 인자에 넣어주면 인식하지 않을까? 싶어서

     

    const WidgetContainer = styled.div<{type:string|undefined, isstuck:boolean|undefined}>`
    	background-color: ${(props)=>props.id};
    `
    
    const Widget = ({id, type, isstuck, title, children}:WidgetProps) => {
        return (
            <WidgetContainer type={type} id='#780404' isstuck={isstuck}>
                ...
            </WidgetContainer>
        )
    }

     

    이렇게 직접 값을 줘 봤더니 styled.div에서 id 인자를 명시해주지 않아도 전달한 색상 값이 적용 되네요.

     

     

    id 값을 배경색으로 한 위젯

    이렇게 배경색이 잘 변합니다.

     

    그리하여 저의 결론은 기본 생성되는 속성은 props로 사용하지 말자. 입니다.

     

     

     

    추가로 배울 만한 정보

    앞서 styled-component의 경우 class가 자동으로 생성된다고 했는데요, 이에 대해 styled-components가 어떻게 작동하는지 더 자세히 설명해주는 글을 찾을 수 있었습니다.

     

    보통 내부 동작 원리 같은 건 잘 찾기 힘들고, 대충 고개를 끄덕이며 쓰기 십상인데 너무 좋은 자료라고 생각됩니다.

     

     

    styled-components는 어떻게 동작할까?

    최근 react 커뮤니티에서는 (styled-components, emotion, etc)의 인기가 날이 갈수록 높아지고 있습니다. 는 2019년 기준 작년 12월에 비해 npm 주간 다운로드 수가 약 2배(65만 => 13…

    john015.netlify.app

     

Designed by Tistory.