๐Ÿ’…Styled-components์—์„œ props ๋˜‘๋˜‘ํ•˜๊ฒŒ ๋„˜๊ฒจ์ฃผ๊ธฐ (feat. Received `true` for a non-boolean attribute)

์ง€์›ยท2023๋…„ 7์›” 29์ผ
5

styled-component๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€

Warning: Received `true` for a non-boolean attribute `{props ๋ช…}`.

์œ„์™€ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋งˆ์ฃผ์ณค๋‹ค.

์–ด๋””์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ฐพ์•„๋ณด๋‹ˆ, ๋งŒ๋“ค์–ด ๋‘์—ˆ๋˜ <TextDiv>๋ผ๋Š” common component์˜€๋‹ค.

<TextDiv nowrap>์ƒ์„ธ ๋‚ด์šฉ</TextDiv>

TextDiv๋Š” ์ปฌ๋Ÿฌ, ์‚ฌ์ด์ฆˆ, ํฐํŠธ ๊ตต๊ธฐ, wrap ์—ฌ๋ถ€ ๋“ฑ์„ props๋กœ ๋ฐ›์•„์„œ Text๊ฐ€ ๋“ค์–ด๊ฐ„ div๋ฅผ ์ปค์Šคํ…€ ํ•  ์ˆ˜ ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ์˜€๋Š”๋ฐ, ์ € props ์ค‘์—์„œ nowrap์ด ์—๋Ÿฌ์˜ ์›์ธ์ด์—ˆ๋‹ค.

import styled from 'styled-components';

export interface TextDivProps {
  color?: string;
  size?: number;
  weight?: number;
  nowrap?: boolean;
}

export const TextDiv = styled.div<TextDivProps>`
  color: ${({ color }) => (color ? color : 'black')};
  font-size: ${({ size }) => (size ? size : 14)}px;
  font-weight: ${({ weight }) => (weight ? weight : 400)};
  white-space: ${({ nowrap }) => (nowrap ? 'nowrap' : 'normal')};
`;

nowrap์€ non-boolean attribute์ธ๋ฐ, true, false์ธ boolean ๊ฐ’์œผ๋กœ ๋ฐ›์•˜๋‹ค๋Š” ๋‚ด์šฉ์˜ ์—๋Ÿฌ์ด๋‹ค.

์™œ warning์ด ๋ฐœ์ƒํ–ˆ์„๊นŒ??

1) ํ‘œ์ค€, ๋น„ํ‘œ์ค€์— ๋Œ€ํ•œ ๋ฌธ์ œ

๊ธฐ๋ณธ์ ์œผ๋กœ HTML ์‹œ๋ฉ˜ํ‹ฑ ํƒœ๊ทธ๋Š” width, height, id ๋“ฑ๋“ฑ ๋‹ค์–‘ํ•œ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
์ด๋Ÿฌํ•œ ์†์„ฑ๋“ค์„ ์šฐ๋ฆฌ๋Š” HTML ํ‘œ์ค€ ์†์„ฑ์ด๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜ ์žˆ๋‹ค.

HTML ํ‘œ์ค€์†์„ฑ
https://developer.mozilla.org/ko/docs/Web/HTML/Attributes
ํ‘œ์ค€ ์†์„ฑ์ด ์•„๋‹Œ ๊ฒƒ๋“ค์€ ๋น„ํ‘œ์ค€ ์†์„ฑ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ alt={true}๋“ฑ ๊ณผ ๊ฐ™์ด, string์œผ๋กœ ์ „๋‹ฌํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š” ํ‘œ์ค€ ์†์„ฑ์„ boolean์œผ๋กœ ์ „๋‹ฌํ•˜๊ฒŒ ๋˜๋ฉด non-boolean attribute warning์ด ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.

2) ๋น„ํ‘œ์ค€ ์†์„ฑ์ธ๋ฐ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š” ๊ฒƒ๋“ค?

styled-component ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Styled-component Passed Props
https://styled-components.com/docs/basics#passed-props

If the styled target is a simple element (e.g. styled.div), styled-components passes through any known HTML attribute to the DOM. If it is a custom React component (e.g. styled(MyComponent)), styled-components passes through all props.
Note how the inputColor prop is not passed to the DOM, but type and defaultValue are. That is styled-components being smart enough to filter non-standard attributes automatically for you.

์‹ค์ œ DOM ์—˜๋ฆฌ๋จผํŠธ์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์—, styled-components ๋‚ด๋ถ€์—์„œ ๋น„ํ‘œ์ค€ ์†์„ฑ์„ ์ž๋™์œผ๋กœ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜ ๋งํฌ์—์„œ ํ•„ํ„ฐ๋ง ๋˜๋Š” ๋น„ํ‘œ์ค€ ์†์„ฑ์— ์–ด๋–ค ๊ฒƒ๋“ค์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

https://github.com/emotion-js/emotion/blob/main/packages/is-prop-valid/src/props.js

3) nowrap์€ 2๋ฒˆ์— ํ•ด๋‹น์•ˆ๋˜๋Š”๋ฐ ์™œ ์•ˆ๋˜๋Š”๋ฐ?

nowrap์€ ๋น„ํ‘œ์ค€ ์†์„ฑ์ด๊ณ , 2๋ฒˆ์˜ styled-component์—์„œ ํ•„ํ„ฐ๋ง ํ•˜๋Š” attribute์ด๋ฆ„๋„ ์•„๋‹ˆ์ง€๋งŒ, ์™œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฑธ๊นŒ?

nowrap ๊ฐ™์€ ์†์„ฑ์€ CSS์˜ white-space ์†์„ฑ์— ํ•ด๋‹นํ•˜๋ฉฐ, HTML์˜ ํ‘œ์ค€ ์†์„ฑ์€ ์•„๋‹ˆ์ง€๋งŒ DOM์— ์ง์ ‘ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” styled-components์—์„œ๋„ ์ด ์†์„ฑ์„ DOM์œผ๋กœ ์ „๋‹ฌํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋ ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด๋ฅผ boolean ๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ๊ฒฝ๊ณ  ๋ฉ”์„ธ์ง€๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

1. DOM์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š๋Š” props ๋ช…์œผ๋กœ ๋Œ€์ฒดํ•œ๋‹ค.

  • noWrap => isNoWrap ๋“ฑ์œผ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ

2. (์ถ”์ฒœ) prefix๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (styled-components 5.1v ๋ถ€ํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ)

  • prefix '$'๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, props ๊ฐ€ ์‹ค์ œ DOM ์š”์†Œ์— ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.
  • noWrap => $noWrap

Transient props v5.1

If you want to prevent props meant to be consumed by styled components from being passed to the underlying React node or rendered to the DOM element, you can prefix the prop name with a dollar sign ($), turning it into a transient prop.

์™œ prefix๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ?

  1. ์„ฑ๋Šฅ ์ตœ์ ํ™”:
    styled-components๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ถˆํ•„์š”ํ•œ ์†์„ฑ์ด DOM์— ์ „๋‹ฌ๋˜๋Š” ๊ฒƒ์„ ์ตœ๋Œ€ํ•œ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค. DOM์— ๋ถˆํ•„์š”ํ•œ ์†์„ฑ์ด ์ „๋‹ฌ๋˜๋ฉด, ์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ํ•ด๋‹น ์†์„ฑ์„ ํ•ด์„ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ์ €ํ•˜์˜ ์›์ธ์ด ๋œ๋‹ค.

  2. ์Šคํƒ€์ผ ๊ฐ€๋…์„ฑ ๋ฐ ์œ ์ง€๋ณด์ˆ˜์„ฑ:
    ์ปดํฌ๋„ŒํŠธ๋ฅผ ์Šคํƒ€์ผ๋งํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์†์„ฑ ์ด๋ฆ„์ด DOM์— ์ „๋‹ฌ๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์€ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค. prefix๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜๋Š” ์†์„ฑ๊ณผ ์‹ค์ œ๋กœ DOM์— ์ „๋‹ฌ๋˜๋Š” ์†์„ฑ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  3. ์ฝ”๋“œ ์ถฉ๋Œ ๋ฐฉ์ง€:
    ๋งŒ์•ฝ styled-components์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์†์„ฑ๊ณผ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›ํ•˜๋Š” ๋น„ํ‘œ์ค€ ์†์„ฑ ์ด๋ฆ„์ด ์ถฉ๋Œํ•œ๋‹ค๋ฉด, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด prefix๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, DOM์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ์†์„ฑ์œผ๋กœ ๋Œ€์ฒดํ•จ์œผ๋กœ์จ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

References
https://mygumi.tistory.com/382

profile
์•ˆ๋…•ํ•˜์„ธ์š” ์ง€์›์ž…๋‹ˆ๋‹ค.

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2023๋…„ 7์›” 29์ผ

์ข‹์€ ๊ธ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ž์ฃผ ์˜ฌ๊ฒŒ์š” :)

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ