돌멩이 하나/에러는 미래의 연봉

styled-components에서 custom props 사용하기

미래에서 온 개발자 2023. 7. 28. 18:28

기술 과제를 진행하면서 styled-components를 사용해 공통 ui 컴포넌트를 만들던 중 input 입력란의 텍스트 정렬을 다르게 가져가야 할 필요가 생겼다. 아래의 화면 이미지와 같이 우편번호 input은 중앙정렬, 그 외에 input은 일반적인 좌측 정렬로 화면 디자인이 구성되어 있었다. 
 

배송지 입력란 화면

 
이를 위해 input ui 컴포넌트에서 prop으로 textAlign 값을 줘서 제어하려고 시도했다.
 

// 공통 ui 컴포넌트 선언부
export const Input = styled.input`
  box-sizing: border-box;
  width: ${(props) => props.width || 'inherit'};
  height: 40px;
  padding: 9px 13px;
  border: 1px solid var(--gray100);
  border-radius: 6px;
  color: var(--black);
  font-size: 12px;
  text-align: ${(props) => props.textAlign || 'inherit'};

  &::placeholder,
  &:disabled {
    background-color: var(--white);
    color: var(--gray600);
  }

  &:focus {
    outline: 1px solid var(--green200);
  }
`;


// Input 컴포넌트 호출부
        <Input
          placeholder='우편번호'
          width='30%'
          textAlign='center'
          value={postcode}
          disabled
        />

 
그러자 정상적으로 동작은 했지만 콘솔 창에 다음과 같은 경고가 떴다.

Warning: React does not recognize the `textAlign` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `textalign` instead. If you accidentally passed it from a parent component, remove it from the DOM element.

 

 
React에서 DOM 엘리먼트로 전달되는 모든 prop들이 React에서 사전에 알고 있는 유효한 HTML 속성이어야 하는데, 정의되지 않은 속성을 전달하려고 하니 경고를 해주는 거였다. React에서는 DOM 속성 이름을 카멜 케이스(camelCase)로 인식한다. 즉, textAlign과 같이 카멜 케이스로 작성된 속성 이름은 React에서 자동으로 textalign과 같이 소문자로 변환하여 DOM에 적용하려고 한다. 이렇게 하면 React는 속성 이름을 정상적으로 인식하고 DOM에 전달할 수 있다.
 

 
React 경고 메시지에서 하란대로 하면 해결되는 경우가 많다. 그럼 이번에도 하란대로 선언부와 호출부 양쪽에서 textAlign을 소문자로 바꿔보자. 
 

styled-components: it looks like an unknown prop "textalign" 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 using transient props (`$` prefix for automatic filtering.)

 

그랬더니 이번에는 styled-componets 경고가 뜬다. 제시해 주는 해결책은 두 가지이다. 
 
 
1. StyleSheetManager 사용
@emotion/is-prop-valid 패키지를 설치한 후, StyleSheetManager를 사용하여 unknown props를 자동으로 필터링할 수 있다. 
 

import { StyleSheetManager } from 'styled-components';
import isPropValid from '@emotion/is-prop-valid';

// ...

const App = () => {
  return (
    <StyleSheetManager shouldForwardProp={prop => isPropValid(prop)}>
      {/* 이하 컴포넌트 구조 */}
    </StyleSheetManager>
  );
};

// ...

 
2. Transient props 사용
Transient props를 사용하여 해당 prop를 필터링하면, DOM으로 전달되지 않으므로 경고가 발생하지 않는다. 이를 위해 styled-components에서는 prefix $를 사용한다. 선언부와 호출부 양쪽에서 textalign 대신에 $textalign으로 작성해 주면 경고가 사라진다.
 
그리고 개발자 도구로 확인해 보면 더이상 textalign 속성이 DOM에 표시되지 않는다. 

 
https://styled-components.com/docs/api#transient-props

styled-components: API Reference

API Reference of styled-components

styled-components.com

 
이런 custom prop을 쓸 일이 많다면 패키지 설치 후 StyleSheetManager로 한 번에 처리해주는 편이 좋겠지만, 과제에서는 custom props가 많지 않아서 prefix $를 사용해서 간단하게 에러를 해결했다.