우리는 리액트 입문 10일차이지만 이 미션을 완성해야만 해..!
처음 레벨2의 payments 미션을 만났을 때 솔직히 막막했다. 시간은 없고 미션은 끝내야하고,,
나는 리액트의 가장 큰 장점 중 하나를 컴포넌트의 재사용이라고 생각했다. 하지만 컴포넌트를 어디까지 나눌 것인가에 대한 이야기를 시작하자 답답해졌다. 가장 작은 단위로 쪼개서 필요에 따라 재사용 하고 싶은데 그럴 능력도 시간도 우리에겐 없었다. 그래서 일단 컴포넌트를 크게크게 자르기로 결정! 카드번호, 만료일, 소유자 이름, 보안 코드, 카드 비밀번호 이렇게 한 묶음이다.
payments에서 가장 재사용이 활발한 친구는 input 요소이다. 내 로직에서 끝까지 가장 날 괴롭힌 컴포넌트인 카드 번호 인풋의 코드를 예시로 들겠다. 이런 애들이 각 컴포넌트마다 따로 있는 거임. 여기서 St. 어쩌고는 스타일 컴포넌트니 크게 신경쓰지말자. 그래도 혹시 모르니 아래 코드 추가는 해두겠음
//CardNumberInput.tsx
import React, { useState, useEffect } from "react";
import St from "./styled";
type CardNumberInputProps = {
changeCardNumber: (e: React.ChangeEvent<HTMLInputElement>) => void;
CardNumberHidden: string;
};
function CardNumberInput({
changeCardNumber,
CardNumberHidden,
}: CardNumberInputProps) {
return (
<section>
<St.Title>카드 번호</St.Title>
<St.InputSection>
<St.Input
type="text"
value={CardNumberHidden}
onInput={changeCardNumber}
></St.Input>
</St.InputSection>
</section>
);
}
export default CardNumberInput;
// CardNumberInput의 스타일 컴포넌트
import styled from "styled-components";
const St = {
InputSection: styled.section`
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
width: 100%;
height: 7vh;
border-radius: 7px;
background: #ecebf1;
`,
Input: styled.input`
width: 90%;
border: none;
text-align: center;
background: inherit;
font-size: 20px;
letter-spacing: 2px;
`,
Title: styled.h1`
padding-bottom: 10px;
font: 500 14px/16px "Roboto";
align-items: center;
letter-spacing: -0.085em;
color: #525252;
`,
};
export default St;
지금은 input 태그에 속성을 별로 안가지고 있는데 버그 fix하고 기능 추가하니까 너무너무 길어짐. 그리고 스타일 컴포넌트에서 inputSection이랑 input은 몇 개 빼고 다 똑같은데 하나하나 써주니까 너무 귀찮드라.. 그래서 input 태그 자체를 컴포넌트로 분리했당!
Input 컴포넌트
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;
//};
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
isRequired: boolean;
inputRef?: React.RefObject<HTMLInputElement>;
}
function Input({ isRequired, inputRef, ...props }: InputProps) {
return (
<Style.InputSection>
<Style.Input
{...props}
required={isRequired ? true : false}
ref={inputRef}
/>
</Style.InputSection>
);
}
export default Input;
원래 하나하나 인자 타입 만들어줬는데 이렇게 기본 input 속성 타입에서 확장하는게 더 편하다!
다 빼고 중요한건 인자 부분인 { isRequired, inputRef, ...props } 여기임
전체 props중에서 isRequired, inputRef에 해당되는 props 빼고 나머지는 Spread Operator로 가져오는 거.
그리고 나서 input 태그에 그대로 Spread Operator로 넣어주면 하나하나 하드코딩 안해도 된당! 아 Spread Operator 쓸 때는 props 보다는 나머지를 뜻하는 rest를 사용한다고 한다. 근데 나는 쌩초보라 그런거 몰랐음🥲
그러면 CardNumberInput에서는 어떻게 보내주느냐?
CardNumberInput 컴포넌트
const props = {
type: "text",
value: cardNumberHidden,
isRequired: true,
onInput: (e: React.ChangeEvent<HTMLInputElement>) => {
isNumber(e);
changeCardNumber(e);
},
onBlur: isRightLength,
};
return (
<section>
<Style.Title>카드 번호</Style.Title>
<ThemeProvider theme={theme}>
<Input {...props} />
</ThemeProvider>
<InputGuide warningText={warningText} />
</section>
);
이르케 밖에서 props라는 이름의 객체로 보낼거 묶어서 보냈다. 나머지는 거의 원래 코드랑 비슷함. 아 객체이름은 그냥 내가 맘대로 한거라 props말고 다른 이름 쓰도록 하세요. 저도 처음 해봐서 이렇게 했답니다.
뭔가 이상하죠? ThemeProvider가 갑자기 띠용 나왔잖아요! 바로 Input 컴포넌트 재사용을 더 똑똑하게 할 수 있는 친구랍니다. 저 친구로 변하는 스타일만 딱딱 바뀌도록 해줄거에요. 그건 다음 글에서 알려드리겠서요^^7 안뇽~
Spread Operator
- 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시킬 수 있음.
전개 구문 - JavaScript | MDN
전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시
developer.mozilla.org
'FE 기술 > React' 카테고리의 다른 글
React와 SSE(Server Sent Events)로 실시간 채팅 구현하기 (0) | 2024.11.18 |
---|---|
[React] 무한스크롤 구현하기 (useInfiniteQuery, Cursor-based Pagination) (0) | 2024.11.18 |
Webpack 기반의 React & TypeScript 환경 세팅 (0) | 2023.07.06 |
React) useEffect 사용방법, dependency array (0) | 2023.04.25 |
React) ThemeProvider로 필요한 스타일만 바꾸기 [재사용 가능한 Input 컴포넌트 2] (0) | 2023.04.24 |