interface Props {
name: string;
age: number;
}
export const Component: React.FC<Props> = props => {
const {name, age} = props;
return (
<div>
`이름: ${name} 나이 : ${age}`
</div>
)
}
기본적으로 props로 받는 컴포넌트의 경우 props만 일치시켜주면 동일하게 사용가능하다는 장점이 있다.
특위 위와같이 간단한 컴포넌트의 경우에 적합하다.
다만, 이벤트 핸들링이나, props가 많아지게 될 경우 코드가 길어지고, 가독성이 떨어지는 단점도 있다.
// 각각은 다른 파일입니다.
/** 추상 클래스로 VM 선언 (abstractComponentVM.ts) */
abstract class AbstractComponentVM {
abstract readonly name: string;
abstract readonly age: number;
get nameWithAge() {
return `이름 : ${name} 나이 : ${age}`;
}
}
/** 컴포넌트 (Component.tsx) */
interface Props {
vm: AbstractComponentVM;
}
export const Component: React.FC<Props> = props => {
const {nameWithAge} = props.vm;
return (
<div>
{nameWithAge}
</div>
);
}
/** 추상 클래스 상속 받아 구현 (componentVM.ts) */
class ComponentVM extends AbstractComponentVM {
readonly name: string = '모기';
readonly age: number = 28;
}
/** 실제 컴포넌트 사용처 (Home.tsx) */
export const Home: React.FC = () => {
const [vm] = useState(new ComponentVM());
return (
<Component vm={vm}/>
);
}
abstract class를 활용할 경우 이런 문제가 어느정도 해소되며, template method pattern 중 hook이라고 불리는 패턴을 통해 코드의 캡슐화를 가져올 수 있다.
mobX와 같이 observing할 수 있는 상태에 가장 적합한 로직이다.
추가적인 장점으로 비즈니스 로직과 뷰 단 로직의 완전한 분리가 가능하다.
위 형식으로 개발을 진행할 경우 view와 vm은 1:1로 매핑 관계를 형성하게 된다.
물론, abstract class기 때문에 이를 구현해줘야 한다는 단점이 있고, 중복 코드가 발생한다는 여지는 있으나, 코드의 재사용성을 높일 수 있다.
즉, abstract class의 데이터 형식만 맞춰주면, 어디서든 동일하게 동작하는 컴포넌트를 구현할 수 있다.