FE 기술/React

React) ThemeProvider로 필요한 스타일만 바꾸기 [재사용 가능한 Input 컴포넌트 2]

Rulu_ 2023. 4. 24. 20:00
그래서 각기 다른 길이를 가지고 있는 컴포넌트에게 어떻게 스타일을 입혀주지?

ThemeProvider 사용법 말고  컴포넌트 분리자체가 궁금하면 1번 글 보러가세요

일단 어떻게든 분리는 했는데... 그래서 어떻게 style을 넣어줄지 고민이 되었어요. 그러던 중 ThemeProvider을 알게 되었음.

 

ThemeProvider 장점

1. 매번 노가다 안해도 괜찮음

2. 스타일 선언 순서에 대한 일관성 확보 가능

3. 컴포넌트 자체를 재사용하기 편함

 

이정도가 내가 생각한 ThemeProvider의 장점이에요. 더 있을 수도 있는데 아직 그거까지는 모르겠답니다. 나중에 알게되고 + 안귀찮으면 업데이트 할게용><

 

사용법

재사용의 대상이 되는 컴포넌트

 내 코드에서는 Input 컴포넌트겠죠? 일단 다시 코드를 봅시다

Input.tsx

import React from "react";
import Style from "./InputStyled";

type InputProps = {
  type: string;
  isRequired: boolean;
  onInput: (e: React.ChangeEvent<HTMLInputElement>) => void;
  id?: string;
  value?: string;
  minLength?: number;
  maxLength?: number;
  placeholder?: string;
  inputRef?: React.RefObject<HTMLInputElement>;
  onBlur?: (e: React.ChangeEvent<HTMLInputElement>) => void;
};

function Input({ isRequired, inputRef, ...props }: InputProps) {
  return (
    <Style.InputSection>
      <Style.Input
        {...props}
        required={isRequired ? true : false}
        ref={inputRef}
      />
    </Style.InputSection>
  );
}

export default Input;

이 친구가 어디서 사용되냐에 따라서 스타일이 바껴야해요 스타일 코드를 봐봅시다.

InputStyle.tsx

import styled from "styled-components";

const Style = {
  InputSection: styled.section`
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;

    width: ${(props) => props.theme.inputSectionWidth};
    height: 6vh;

    border-radius: 7px;

    background: #ecebf1;
  `,

  Input: styled.input`
    border: none;
    text-align: center;
    background: inherit;

    width: ${(props) => props.theme.width};
    font-size: ${(props) => props.theme.size};
    letter-spacing: ${(props) => props.theme.spacing};
  `,
};

두둥! 바뀌지 않는 애들은 똑같이 써주고 바껴야하는 친구들에게 어떤 속성을 줄건지 정해주는거에요. 하지만 props가 들어오지 않는 경우도 있겠죠? 그럴 땐 이렇게 defaul값을 정해준답니다.

Style.Input.defaultProps = {
  theme: {
    inputSectionWidth: "",
    width: "",
    size: "",
    spacing: "0px",
  },
};
export default Style;

이제 스타일 컴포넌트에 들어오는 theme의 속성이 있으면 그 값으로 위에 스타일이 바뀔거고 아니면 이 defaultProps를 가지고 스타일이 정해지는거랍니다

 

이제 사전 준비가 다 끝났어요!

 

provider 적용해서 스타일 바꾸기

이제 다시 cardNumberInput을 봐야해요. 

스타일을 바꿔야하는 대상인 Input 컴포넌트를 <ThemeProvider>로 감싸주고 ThemeProvider여기에 바뀔 theme을 보내줍니다. 그러면 스타일 컴포넌트에서 props.theme으로 해당 속성에 접근이 가능한거에요

 

const theme = {
    inputSectionWidth: "100%",
    width: "90%",
    size: "20px",
    spacing: "2px",
  };

  return (
    <section>
      <Style.Title>카드 번호</Style.Title>
      <ThemeProvider theme={theme}>
        <Input {...props} />
      </ThemeProvider>
      <InputGuide warningText={warningText} />
    </section>
  );

 

아직 저는 Input컴포넌트에서 간단한 몇가지만 이용해서 적용해보았지만 응용하면 반응형 이런식으로 가능해질 것 같네요! 그건 나중에 하게 되면 추가할게요(안귀찮으면) 밑에 참고자료 올려두겠습니당

 

 

styled-components: Advanced Usage

Theming, refs, Security, Existing CSS, Tagged Template Literals, Server-Side Rendering and Style Objects

styled-components.com