Skip to main content

커스텀 컴포넌트 고급 사용법

이 문서에서는 커스텀 컴포넌트의 고급 기능과 패턴에 대해 설명합니다.

복잡한 상태 관리

복잡한 컴포넌트의 경우 여러 상태를 관리해야 할 수 있습니다:

import { ReactElement } from 'react';
import { CustomComponentRenderProps, useComponentState, useLogger } from '@hops/custom-component';

function ComplexComponent(props: CustomComponentRenderProps<OwnProps>): ReactElement {
// 여러 상태 관리
const [value, setValue] = useComponentState<string>('value', props.defaultValue);
const [isValid, setIsValid] = useComponentState<boolean>('isValid', true);
const [errors, setErrors] = useComponentState<string[]>('errors', []);
const [history, setHistory] = useComponentState<string[]>('history', []);

// 로컬 상태 (외부에서 접근 불가)
const [localState, setLocalState] = useState<string>('');

// 상태 업데이트 로직
const updateValue = (newValue: string) => {
setValue(newValue);

// 유효성 검사
const validationErrors = validate(newValue);
setIsValid(validationErrors.length === 0);
setErrors(validationErrors);

// 히스토리 업데이트
setHistory((prev) => [...prev, newValue].slice(-5)); // 최근 5개 항목만 유지
};

// 컴포넌트 UI 렌더링...
}

워크플로우와의 통합

커스텀 컴포넌트의 상태는 워크플로우에서 사용할 수 있습니다:

  1. useComponentState로 관리되는 상태는 워크플로우의 입력으로 사용 가능
  2. 워크플로우의 출력은 컴포넌트 프로퍼티로 전달 가능

예를 들어, 데이터 입력 폼 컴포넌트는 다음과 같이 사용할 수 있습니다:

import { memo, ReactElement } from 'react';
import { CustomComponentRenderProps, useComponentState, useLogger } from '@hops/custom-component';
import { FormControl, Button, Typography } from '@hops/design-system';

interface DataEntryFormOwnProps {
workflowResult: {
message?: string;
};
}

function DataEntryForm(props: CustomComponentRenderProps<DataEntryFormOwnProps>): ReactElement {
// 폼 데이터를 워크플로우에서 사용하여 저장 작업 수행 가능
const [formData, setFormData] = useComponentState<Record<string, any>>('formData', {});

// 워크플로우의 결과를 표시하기 위해 props.workflowResult 사용 가능

return (
<FormControl>
{/* 폼 필드들 */}
<Button onClick={() => setFormData(/* 폼 데이터 */)}>저장</Button>

{/* 워크플로우 결과 표시 */}
{props.workflowResult && <Typography>{props.workflowResult.message}</Typography>}
</FormControl>
);
}

export default memo(DataEntryForm);

내부 이벤트 처리

내부 이벤트 처리가 필요한 경우 다음과 같이 구현할 수 있습니다:

import { memo, ReactElement } from 'react';
import { CustomComponentRenderProps, useComponentState } from '@hops/custom-component';
import { FormControl, Button, Input, FormLabel, Typography } from '@hops/design-system';

interface DataEntryFormOwnProps {
initialValue?: string;
}

function DataEntryForm(props: CustomComponentRenderProps<DataEntryFormOwnProps>): ReactElement {
const [formValue, setFormValue] = useComponentState<string>('formValue', props.initialValue || '');
const [submitted, setSubmitted] = useComponentState<boolean>('submitted', false);

// Input 입력 이벤트 처리
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormValue(e.target.value);
setSubmitted(false);
};

// 제출 이벤트 처리
const handleSubmit = () => {
if (formValue.trim()) {
setSubmitted(true);
}
};

return (
<div>
<FormControl>
<FormLabel>데이터 입력</FormLabel>
<Input value={formValue} onChange={handleInputChange} placeholder="값을 입력하세요" />
</FormControl>

<Button onClick={handleSubmit}>저장</Button>

{submitted && <Typography>저장된 값: {formValue}</Typography>}
</div>
);
}

export default memo(DataEntryForm);

성능 최적화

일반적으로 사용되는 React의 최적화 기법을 사용하세요.

메모이제이션

가능한 모든 컴포넌트를 memo로 감싸서 불필요한 리렌더링을 방지합니다:

export default memo(MyComponent);

useMemo 및 useCallback

계산 비용이 높은 연산이나 함수는 useMemouseCallback을 사용하여 최적화합니다:

// 비용이 높은 계산 메모이제이션
const processedData = useMemo(() => {
return expensiveDataProcessing(props.data);
}, [props.data]);

// 이벤트 핸들러 메모이제이션
const handleChange = useCallback(
(value: string) => {
setValue(value);
validate(value);
},
[setValue, validate],
);
tip

복잡한 커스텀 컴포넌트를 작성할 때는 작은 하위 컴포넌트로 분리하는 것이 좋습니다. 이렇게 하면 코드 관리와 디버깅이 더 쉬워집니다.