이슈 : 개발이 지속됨에 따라 다양한 디자인 형태의 부가족인 요소가 계속 추가되어 props가 지속적으로 늘어있음.

1. 기존 컴포넌트
interface FieldProps {
name: string
title?: string
description?: string
inputType?: string
fieldType?: 'default' | 'leftImg'
buttonText?: string
isButtonDisabled?: boolean
placeholder?: string
defaultValue?: string
isRequiredField?: boolean
isReadOnly?: boolean
isLoading?: boolean
pointerEvents?: string
autoComplete?: string
leftIconSrc?: string
rightIconSrc?: string
margin?: string
pattern?: string
onClickButton?: () => void
onClickInput?: () => void
}
export const Field = ({
name,
title = '',
description = '',
inputType = '',
fieldType = 'default',
buttonText = '',
isButtonDisabled = false,
placeholder = '',
defaultValue = '',
isRequiredField = false,
isReadOnly = false,
isLoading = false,
pointerEvents = 'auto',
autoComplete = 'on',
leftIconSrc = '',
rightIconSrc = '',
margin = '',
pattern = undefined,
onClickButton,
onClickInput,
}: FieldProps) => {
return (
<Styles.Wrap>
{title && (
/..../
)}
<Styles.FieldBox
isError={isError()}
isSuccessField={isSuccessField}
isReadOnly={isReadOnly}
>
{fieldType === 'leftImg' && (
/..../
)}
<Input
{...rest}
/>
<Styles.IconBox>
{!isLoading && buttonText && (
/.../
)}
{!isLoading && rightIconSrc && (
/.../
)}
{isLoading && (
/.../
)}
</Styles.IconBox>
</Styles.FieldBox>
</Styles.Wrap>
)
}
export default Field
기존 코드는 재사용하기 위해 요구사항이 늘어날수록 Props를 계속 추가하여 Props가 너무 많이 늘어난 상태입니다.
이렇게 Props가 늘어남에 따라 사이트이펙트 발생할 우려가 생기고, 유지보수가히가 어려워져 개선할 방법을 고민하였습니다.
2. 합성 컴포넌트(Compound Component 패턴)
각 컴포넌터를 조합해 사용하는 컴포넌트 패턴
2-1. 컴포넌트 분리
기존의 Field 컴포넌트를 메인, 서포 컴포넌트로 분리하였습니다.
메인
interface FieldMainProps {
children: ReactNode
name: string
margin?: string
}
type FieldValues = { [key: string]: string }
const FieldMain = ({ children, margin, name }: FieldMainProps) => {
const {
formState: { errors },
} = useFormContext<FieldValues>()
const fieldError = errors?.[name]
const getErrorMessage = () => fieldError?.message ?? ''
return (
<FieldProvider name={name}>
<Styles.Wrap margin={margin}>
{children}
{getErrorMessage() && (
<Styles.FieldMessage>{getErrorMessage()}</Styles.FieldMessage>
)}
</Styles.Wrap>
</FieldProvider>
)
}
export default FieldMain
서브
interface FieldProps {
children: ReactNode
isRequiredField?: boolean
}
const FieldTitle = ({ children, isRequiredField }: FieldProps) => {
return (
<Styles.FieldTitle isRequiredField={isRequiredField}>
<Styles.Title>{children}</Styles.Title>
</Styles.FieldTitle>
)
}
export default FieldTitle
2-2. 메인 & 서브 컴포넌트를 묶어서 export
import FieldMain from '@/components/molecules/Field/FieldMain'
import FieldTitle from '@/components/molecules/Field/FieldTitle'
import FieldInputBox from '@/components/molecules/Field/FieldInputBox/FieldInputBox'
const Field = Object.assign(FieldMain, {
Title: FieldTitle,
InputBox: FieldInputBox, //InputBox이하 생략..
})
export default Field
2-3. 컴포넌트 사용
<Field name="name">
<Field.Title>이름 수정</Field.Title>
<Field.InputBox>
<Field.InputBox.Input />
</Field.InputBox>
</Field>
합성 컴포넌트 도입으로 지속적으로 한 컴포넌트에만 Props가 너무 많이 늘어나는 문제가 해결되었으며, 유연성이 높아졌습니다.
'React' 카테고리의 다른 글
React-Tooltip 개선 (0) | 2023.10.05 |
---|---|
JSX 조건부 렌더링 : 삼항 연산자 vs && (0) | 2022.06.29 |
Atomic Design Pattern (0) | 2022.05.13 |
나는 useCallback을 남용했다 (3) | 2022.05.04 |
Next.js 수동 설치 (0) | 2022.01.07 |
이슈 : 개발이 지속됨에 따라 다양한 디자인 형태의 부가족인 요소가 계속 추가되어 props가 지속적으로 늘어있음.

1. 기존 컴포넌트
interface FieldProps {
name: string
title?: string
description?: string
inputType?: string
fieldType?: 'default' | 'leftImg'
buttonText?: string
isButtonDisabled?: boolean
placeholder?: string
defaultValue?: string
isRequiredField?: boolean
isReadOnly?: boolean
isLoading?: boolean
pointerEvents?: string
autoComplete?: string
leftIconSrc?: string
rightIconSrc?: string
margin?: string
pattern?: string
onClickButton?: () => void
onClickInput?: () => void
}
export const Field = ({
name,
title = '',
description = '',
inputType = '',
fieldType = 'default',
buttonText = '',
isButtonDisabled = false,
placeholder = '',
defaultValue = '',
isRequiredField = false,
isReadOnly = false,
isLoading = false,
pointerEvents = 'auto',
autoComplete = 'on',
leftIconSrc = '',
rightIconSrc = '',
margin = '',
pattern = undefined,
onClickButton,
onClickInput,
}: FieldProps) => {
return (
<Styles.Wrap>
{title && (
/..../
)}
<Styles.FieldBox
isError={isError()}
isSuccessField={isSuccessField}
isReadOnly={isReadOnly}
>
{fieldType === 'leftImg' && (
/..../
)}
<Input
{...rest}
/>
<Styles.IconBox>
{!isLoading && buttonText && (
/.../
)}
{!isLoading && rightIconSrc && (
/.../
)}
{isLoading && (
/.../
)}
</Styles.IconBox>
</Styles.FieldBox>
</Styles.Wrap>
)
}
export default Field
기존 코드는 재사용하기 위해 요구사항이 늘어날수록 Props를 계속 추가하여 Props가 너무 많이 늘어난 상태입니다.
이렇게 Props가 늘어남에 따라 사이트이펙트 발생할 우려가 생기고, 유지보수가히가 어려워져 개선할 방법을 고민하였습니다.
2. 합성 컴포넌트(Compound Component 패턴)
각 컴포넌터를 조합해 사용하는 컴포넌트 패턴
2-1. 컴포넌트 분리
기존의 Field 컴포넌트를 메인, 서포 컴포넌트로 분리하였습니다.
메인
interface FieldMainProps {
children: ReactNode
name: string
margin?: string
}
type FieldValues = { [key: string]: string }
const FieldMain = ({ children, margin, name }: FieldMainProps) => {
const {
formState: { errors },
} = useFormContext<FieldValues>()
const fieldError = errors?.[name]
const getErrorMessage = () => fieldError?.message ?? ''
return (
<FieldProvider name={name}>
<Styles.Wrap margin={margin}>
{children}
{getErrorMessage() && (
<Styles.FieldMessage>{getErrorMessage()}</Styles.FieldMessage>
)}
</Styles.Wrap>
</FieldProvider>
)
}
export default FieldMain
서브
interface FieldProps {
children: ReactNode
isRequiredField?: boolean
}
const FieldTitle = ({ children, isRequiredField }: FieldProps) => {
return (
<Styles.FieldTitle isRequiredField={isRequiredField}>
<Styles.Title>{children}</Styles.Title>
</Styles.FieldTitle>
)
}
export default FieldTitle
2-2. 메인 & 서브 컴포넌트를 묶어서 export
import FieldMain from '@/components/molecules/Field/FieldMain'
import FieldTitle from '@/components/molecules/Field/FieldTitle'
import FieldInputBox from '@/components/molecules/Field/FieldInputBox/FieldInputBox'
const Field = Object.assign(FieldMain, {
Title: FieldTitle,
InputBox: FieldInputBox, //InputBox이하 생략..
})
export default Field
2-3. 컴포넌트 사용
<Field name="name">
<Field.Title>이름 수정</Field.Title>
<Field.InputBox>
<Field.InputBox.Input />
</Field.InputBox>
</Field>
합성 컴포넌트 도입으로 지속적으로 한 컴포넌트에만 Props가 너무 많이 늘어나는 문제가 해결되었으며, 유연성이 높아졌습니다.
'React' 카테고리의 다른 글
React-Tooltip 개선 (0) | 2023.10.05 |
---|---|
JSX 조건부 렌더링 : 삼항 연산자 vs && (0) | 2022.06.29 |
Atomic Design Pattern (0) | 2022.05.13 |
나는 useCallback을 남용했다 (3) | 2022.05.04 |
Next.js 수동 설치 (0) | 2022.01.07 |