Styled components props 에러

송은·2023년 8월 20일
1

오류

styled-components: it looks like an unknown prop "isEditing" is being sent through to the DOM, which will likely trigger a React console error. 
If you would like automatic filtering of unknown props, you can opt-into that behavior via <StyleSheetManager shouldForwardProp={...}> 
(connect an API like @emotion/is-prop-valid ) 
or consider sing transient props ($prefix for automatic filtering.)

Styled-components 에서 props 로 넘겨줄 때 props 이름에 대해서 인식하지 못하고 오류가 나는 경우가 생겼다.

const App = () => {
  	const [isEditing, setIsEditing] = useState(false);

	return (
    	<Controller isEditing={isEditing}>
        	<AddButton />
        	<DeleteButton />
        </Controller>
    )
}

interface ControllerProps {
  isEditing: boolean;
}

const Controller = styled.div<ControllerProps>`
  display: flex;
  gap: ${({ isEditing }) => (!isEditing ? `8px` : `16px`)};
`;

위의 코드에서는 props 로 넘겨준 isEditing 이라는 이름을 인식을 못하고 있다.


해결

알고보니 Styled-components v5.1 부터는 props 로 넘길 때 $ 달러사인을 이용해서 transient props를 지정해줄 수 있다.

임시 props 라는 의미로 이는 스타일을 위한 컴포넌트에 props 를 전달하고 싶지만, HTML 태그에는 영향을 주지 않기 위해 사용된다.


예시

import styled from 'styled-components';

const Tomato = styled.div`
	background: tomato;
	width: 100px;
	height: 100px;
	border-radius: 100%;
`

const MyTomato = styled(MyTomato)<{ isStevia?: boolean }>`
	background: ${(props) => (props.isStevia ? `red` : `tomato`)};
`

const BadTomato = styled(MyTomato)`
	background: black;
`

css-in-js 는 기본적으로 HTML 기본 태그를 품는 형태로 구현되어 있다.
그리고 styled-components 는 거의 무한히 기존 컴포넌트를 래핑하여 또다른 컴포넌트로 확장이 가능하다.
그러다보니 별도 설정을 하지 않으면, 기본 태그인 Tomato 까지 커스텀으로 정의한 props 가 체인을 타고 모두 거슬러 올라가는 경우가 발생하게 된다.

styled-components 는 순전히 스타일링만을 위해 정의하는 태그(위 코드에서 MyTomato, BadTomato)이므로, 여기서 만든 props 는 HTML 태그로 전달되면 안된다.

그래서 이 때 사용되는 것이 transient props 이다.

$ 기호를 접두사로 붙여주어 해당 props 가 기본 DOM 요소로 전달되어서는 안된다는 뜻을 보낸다.


따라서 처음 문제 코드를 다시 작성하면 이렇게 해결할 수 있다.

const App = () => {
  	const [isEditing, setIsEditing] = useState(false);

	return (
    	<Controller $isEditing={isEditing}>
        	<AddButton />
        	<DeleteButton />
        </Controller>
    )
}

interface ControllerProps {
  $isEditing: boolean;
}

const Controller = styled.div<ControllerProps>`
  display: flex;
  gap: ${({ $isEditing }) => (!$isEditing ? `8px` : `16px`)};
`;

출처

profile
개발자

0개의 댓글