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의 데이터 형식만 맞춰주면, 어디서든 동일하게 동작하는 컴포넌트를 구현할 수 있다.