๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿฟ Project

[SidePJ] ๊นƒํ—ˆ๋ธŒ Issue Cracker 2๋ถ€ - Material UI ์™€ style-components์˜ ๋Œ€๊ฒฐ + ์˜ค๋ฅ˜ ํ•ด๊ฒฐ

by Tamii 2021. 6. 29.
๋ฐ˜์‘ํ˜•

ํ–‰๋ณตํ•œ 2์ฃผ์ฐจ ์‹œ์ž‘ 

๐Ÿ“Œ uuid ์‚ฌ์šฉํ•˜๊ธฐ

React์— ์œ ์ผํ•œ key ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” ํŒจํ‚ค์ง€

React์—์„œ์˜ ์œ ์ผํ•œ key prop ๊ฐ’์€ ๋ฆฌ์•กํŠธ๊ฐ€ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

๊ทธ ์ „์—๋Š” ๋ฐฐ์—ด์˜ key๊ฐ’์— ์ธ๋ฑ์Šค๋ฅผ ๋„ฃ์—ˆ๋Š”๋ฐ, ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค๋Š” 0,1,2,3.. ์ด๋ฏ€๋กœ ๊ณ ์œ ํ•œ ๊ฐ’์ด ์•„๋‹ˆ๋ฏ€๋กœ React๊ฐ€ ๋ Œ๋”๋ง์„ ์ž˜๋ชปํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์œ ํ•œ ๊ฐ’์„ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค.

-> ๋ฐฐ์—ด์— data ์ถ”๊ฐ€ ์ˆ˜์ • ์‹œ ์ „์ฒด ๋ฐฐ์—ด์„ ๋‹ค ์ˆ˜์ •ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 

 

์œ„ ์ฝ”๋“œ์—์„œ uuid ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•ด key๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ์œ ์ผํ•œ UUID๋ฅผ ๋งŒ๋“ค์ˆ˜ ์žˆ๊ณ  ์ด์ฒ˜๋Ÿผ ์œ ์ผํ•œ ID๋Š” ์ถฉ๋Œํ•  ์—ผ๋ ค๊ฐ€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค.

uuid ๊ฐ™์€ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ID๋Š” ์œ ์ผํ•˜๊ณ  ์˜ˆ์ธก๊ฐ€๋Šฅํ•ด์ง€๊ณ , ์šฐ๋ฆฌ๋Š” ๊ฐ ์•„์ดํ…œ์— ๋Œ€ํ•ด ์ƒˆ๋กœ์šด ID๋ฅผ ์ƒ์„ฑํ•  ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผํ•  ํ•„์š”๋„ ์—†์–ด์ง„๋‹ค.

์ฐธ๊ณ  :https://one-it.tistory.com/entry/%EB%B2%88%EC%97%AD-%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%ED%94%BC%ED%95%B4%EC%95%BC-%ED%95%A0-%EC%95%88%ED%8B%B0%ED%8C%A8%ED%84%B4

 


๐Ÿ“Œ ์Šคํƒ€์ผ ๊ด€๋ จ ๊ตฌ์กฐ 

๋งž์•„์š”... ๋„์ „!!!!!!!!!

* Styled component๊ฐ€ ์†์„ฑ์„ props๋กœ ์ „๋‹ฌ๋ฐ›์„ ๋•Œ ์˜ type

interface ProfileImgProps {
  src: string;
  style: {
    width: number;
    height: number;
  };
}

const ProfileImg = ({ src, style }: ProfileImgProps): JSX.Element => {
  return <ProfileImgStyle {...{ src, style }}></ProfileImgStyle>;
};

export default ProfileImg;

const ProfileImgStyle = styled.img`
  width: ${({ style }) => `${style?.width}px`};
  height: ${({ style }) => `${style?.height}px`};
  border-radius: 70%;
  /* object-fit: contain; */
`;

์‚ฌ์šฉ ์‹œ

<ProfileImg style = {width='20px' height='30px'} />

์‚ฌ์‹ค ์ €  style๋ถ€๋ถ„์„ generic์„ ์‚ฌ์šฉํ•˜๋ฉด ์™„๋ฒฝ

 

์ฐธ๊ณ  : https://github.com/styled-components/styled-components/issues/630#issuecomment-547484722

 

๐Ÿ™‚ ๋ฐ˜๋ณต๋œ component style ์ง€์ •

1) ์ •ํ•ด์ง„ style์ด ์žˆ์„ ๋•Œ  : type์œผ๋กœ ๋ฒ„ํŠผ์„ ์‚ฌ์šฉํ•  ๋•Œ LabelLargeGroup

   ์žฅ์ : props ๋ฅผ ๋ฐ›์ง€ ์•Š์Œ์œผ๋กœ์จ component๋‚ด์˜ ํ•œ ๋ถ€๋ถ„์ด ๋ณ€๊ฒฝ๋˜๋„ ์ „๋ถ€ ๋‹ค๋ณ€๊ฒฝ

2) ์ž์ž˜ํ•œ style์ด  ๊ณ„์† ๋ณ€๊ฒฝ๋  ๋•Œ: ํ•˜๋‚˜์˜ component๋ฅผ ๋งŒ๋“ค์–ด์„œ props๋กœ ๋‚ด๋ ค์„œ ์‚ฌ์šฉํ• ๊นŒ IssueHeaderButton

 

1) component๋ฅผ ํ•˜๋‚˜์”ฉ ๋งŒ๋“  ๊ฒฝ์šฐ

const LabelLargeGroup = ({ type }: Prop): JSX.Element => {
  return {
    open: <IssueLabelOpen />,
    closed: <IssueLabelClosed />,
  }[type] as JSX.Element;
};

export default LabelLargeGroup;

const IssueLabelOpen = () => {

  return (
    <IssueLabelStyle>
      <CustomOpenChip
        avatar={<OpenIconGroup type={'label'} />}
        label={OPEN_ISSUE}
        color="primary"
        variant="outlined"
      />
    </IssueLabelStyle>
  );
};

2) props๋กœ ์ผ์ผํžˆ ๋ฐ›์„ ๋•Œ 

const IssueHeaderButton = ({
  icon,
  text,
  count,
}: IssueHeaderButtonProps): JSX.Element => {
  return (
    <IssueHeaderButtonStyle>
      <IconBox>{icon}</IconBox>
      <div>
        <TextBox>{text}</TextBox>
        <CountBox>{count}</CountBox>
      </div>
    </IssueHeaderButtonStyle>
  );
};

๐Ÿ™‚  material UI ์— 

๊ฐ์ฒด๋ฆฌํ„ฐ๋Ÿด๋กœ ๊ทธ๋ฃน๋ณ„๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉ 

๋‹จ material UI์˜ ์†์„ฑ์œผ๋กœ ๋„ฃ์–ด์ค„๋•Œ๋Š” ๋ณ€์ˆ˜๋กœ ์ง€์ •์ด ์•ˆ๋จ

 

 


๐Ÿ“Œ decoded๋ฅผ ๋งค๋ฒˆ ํ•˜๋Š” ๊ณผ์ • ์–ด๋–ป๊ฒŒ ํšจ์œจ์ ์œผ๋กœ ๋ฐ”๊ฟจ์„๊นŒ?

์ˆ˜์ • ์ „

localStorage.setItem('token', data.token);

        const token = localStorage.getItem('token');
        if (!token) return;

        const decoded =
          jwtDecode<{ name: string; profileImageUrl: string }>(token);

        localStorage.setItem('name', decoded.name);
        localStorage.setItem('profileImageUrl', decoded.profileImageUrl);

        history.push(P.ISSUE_LIST);

 

decoded๋ฅผ ๋ณด๊ด€ํ•ด๋†“๊ณ  name๊ณผ profileImg๋กœ ์ €์žฅ์„ ํ–ˆ๋Š”๋ฐ,

 

ํ•ด๋‹น๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ์ •๋ณด์ธ ์ด๋ฆ„๊ณผ ํ”„๋กœํ•„์ด๋ฏธ์ง€๊ฐ€ ๋„ˆ๋ฌด๋‚˜ ์‰ฝ๊ฒŒ ๋…ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ์กฐ์–ธ์„ ๋ฐ›์•˜๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

์ˆ˜์ • ํ›„ 

Recoil์„ ํ™œ์šฉํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ํ™œ์šฉ

export const token = atom({
  key: 'token',
  default: null,
});

export const decodedToken = atom({
  key: 'decodedToken',
  default: {
    name: '',
    profileImageUrl: '',
  },
});
 const decoded = decodedToken && useRecoilValue(decodedToken);
  const profileURL = decoded && decoded.profileImageUrl;

token๊ณผ ์‚ฌ์šฉ์ž ์ •๋ณด์ธ name, profileImg์„ atom์œผ๋กœ ๊ด€๋ฆฌํ•˜์—ฌ  ๊ฐœ์ธ์ •๋ณด๋…ธ์ถœ์„ ํ”ผํ•˜๋ฉด์„œ๋„

๋‹ค์–‘ํ•œ component์—์„œ ํ•„์š”์— ๋”ฐ๋ผ useRecoilValue๋ฅผ ํ†ตํ•ด ๊บผ๋‚ด์™€ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค.

 

์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ž…์žฅ์„œ๋งŒ ์ƒ๊ฐํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž ์ž…์žฅ์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ตํ›ˆ์„ ์–ป์—ˆ๋‹ค.


๐Ÿ“Œ MaterialUI ๋‚ด๋ถ€ ๊ฐ ์š”์†Œ์— Link ๊ฑธ๊ธฐ + ์˜ค๋ฅ˜์™€ ๋””๋ฒ„๊น… ํ•˜๋Š” ๊ณผ์ •

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

 

๋ผ์ฟค๊ณผ ํ•จ๊ป˜ ์—ฌ๋Ÿฌ ์˜ค๋ฅ˜๋“ค์„ ๋งž์ดํ•˜๋ฉฐ ๋‹จ์ˆœํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ์„ ๋•Œ  Warning ์˜†์˜ ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๊ฒ€์ƒ‰ํ•˜๋Š”๊ฒŒ ๋‹ค์ผ๊นŒ? ๋ผ๋Š” ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋˜ ์ค‘ ๋ผ์ฟค์ด ๋””๋ฒ„๊น…์„ ํ•˜๊ณ  ์˜ค๋ฅ˜๋ฅผ ์ฐพ๋Š” ๊ณผ์ •์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์ฃผ์—ˆ๋Š”๋ฐ, ๊ทธ ๊ณผ์ •๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜๊ณ ์ž ํ•œ๋‹ค.

 

[ โŒ Warning ๋ฐ‘ ] 

* ๋””๋ฒ„๊น… ์ˆœ์„œ์™€ ๊ณผ์ •๊ณผ ๋ Œ๋”๋ง ๋˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ 

* ์Šคํƒ์— ์Œ“์—ฌ ์ž‡๋Š” ์ˆœ์„œ๊ฐ€ ๋ณด์—ฌ์ง€๋Š”๊ฒƒ 

* ์˜ค๋ฅ˜๊ฐ€ ๋‚œ ์œ„์น˜๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ 


1) ๊ฒฐ๊ตญ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ ๊ณณ a link 

2) ๊ทธ๋Ÿผ ์–ด๋””์— ์ž‡๋Š” ๋งํฌ์ธ๊ฐ€?๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ ๋ฆฌ์•กํŠธ ์ตœ์ƒ์œ„  ๋ถ€ํ„ฐ  ๋“ค์–ด๊ฐ„๋‹ค (StyleProvider) 

3) IssueList / TabGroup / ButtonGroup  ๊ณ„์†ํ•ด์„œ ๋”ฐ๋ผ ๋“ค์–ด๊ฐ€๋‹ค ๋ณด๋ฉด

4) ButtonGroup๋‚ด์˜ ๋งํฌ(a) ์—์„œ ์ž˜๋ชป๋˜์—ˆ๋‹ค๋Š”๊ฒƒ์„ ์•Œ๊ฒŒ ๋œ๋‹ค.

 

 

[๋ฌธ์ œ์ƒํ™ฉ]

์‚ฌ์šฉํ•˜์ง€๋„ ์•Š์€ MaterialUI์˜ ๋‚ด๋ถ€์š”์†Œ๋“ค์„ UpperCase๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. 

 

TabGroup 

const TabGroup = (): JSX.Element => {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <CustomTabGroup
        size="large"
        color="primary"
        aria-label="large outlined primary button group"
      >
        <Link to="/main/label-list">
          <TabButton startIcon={<LocalOfferIcon />}>
            <TextGroup type={T.SMALL} content={TT.LABEL} color="#6E7191" />
            <CountGroup count={0} color="#6E7191" />
          </TabButton>
        </Link>
        <Link to="/main/milestone">
          <TabButton startIcon={<FlagIcon />}>
            <TextGroup type={T.SMALL} content={TT.MILESTONE} color="#6E7191" />
            <CountGroup count={0} color="#6E7191" />
          </TabButton>
        </Link>
      </CustomTabGroup>
    </div>
  );
};

TabGroup์„ ํ™•์ธํ•ด๋ณด๋ฉด <CutsomTabGroup> ์•ˆ์—  <TabButton>์ด ์žˆ๊ณ  ๊ทธ๊ฒƒ๋“ค์ด <Link>๋กœ ๊ฐ์‹ธ์ ธ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๊ฐ„๊ณผํ•œ ์ ์€ 

<CutsomTabGroup> : Material UI์˜ ButtonGroup์ด๊ณ  

<TabButton> : Material UI์˜ Button ์ด๋‹ค ( ButtonGroup์˜ ๊ฐ์š”์†Œ) 

์ฐธ๊ณ  :https://material-ui.com/components/button-group/

 

ํ˜„์žฌ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Material UI์˜ ๋‚ด๋ถ€์— ์ ‘๊ทผํ•ด Link๋ฅผ ๊ฑธ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

 

 

[ ๊ฒฐ๋ก ]

โญ๏ธmaterial UI ๋‚ด๋ถ€ ์š”์†Œ์— ๋งํฌ๋ฅผ ๊ฐ๊ฐ ๊ฑธ ์ˆ˜ ์—†๋‹ค.

โญ๏ธ Material UI์—๋Š” ๋งํฌ๋ฅผ ๊ฑฐ๋Š” ๋ฐฉ๋ฒ•์ด ๋”ฐ๋กœ ์žˆ๋‹ค.

 

[ ํ•ด๊ฒฐ๋ฐฉ์•ˆ]

1) ButtonGroup์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค

2) Button์— component๋กœ Link๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

 

https://github.com/nygardk/react-share/issues/316

 

ํƒ๊ตฌ ๋์— 2) Button์— component๋กœ Link๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. ๋ฐฉํ–ฅ์œผ๋กœ ๊ฒฐ์‹ฌํ–ˆ๊ณ  

ReactRouter์—์„œ Link๋ฅผ ๊ฐ€์ ธ์™€์„œ Button์˜ component= {Link} ๋กœ ์ „๋‹ฌํ•˜๋ฉด ButtonrGroup๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ทธ ๋‚ด๋ถ€์˜ Button์—๋Š” ๊ฐ๊ฐ ๋งํฌ๋ฅผ ๊ฑธ ์ˆ˜๋„ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

 

 

 

๋Œ“๊ธ€