LocalPaymentMethod
타입useState
에 변형한 데이터를 매핑해준다. ⇒ ViewModel
로 변경ViewModel
을 매핑해준다.//src/Payment.tsx…
export const Payment = ({ amount }: { amount: number }) => {
const [paymentMethods, setPaymentMethods] = useState<LocalPaymentMethod[]>(
[]
);
useEffect(() => {
const fetchPaymentMethods = async () => {
const url = "<https://online-ordering.com/api/payment-methods>";
const response = await fetch(url);
const methods: RemotePaymentMethod[] = await response.json();
if (methods.length > 0) {
const extended: LocalPaymentMethod[] = methods.map((method) => ({
provider: method.name,
label: `Pay with ${method.name}`,
}));
extended.push({ provider: "cash", label: "Pay in cash" });
setPaymentMethods(extended);
} else {
setPaymentMethods([]);
}
};
fetchPaymentMethods();
}, []);
return (
<div>
<h3>Payment</h3>
<div>
{paymentMethods.map((method) => (
<label key={method.provider}>
<input
type="radio"
name="payment"
value={method.provider}
defaultChecked={method.provider === "cash"}
/>
<span>{method.label}</span>
</label>
))}
</div>
<button>${amount}</button>
</div>
);
};
ViewModel
로 만들기커스텀훅을 통해서, 컴포넌트 내부에서 상태를 갖지 않게 할 수 있다. usePaymentMethods 라는 커스텀훅을 만든다. 이렇게만 하더라도 View에 필요한 정보들만 컴포넌트에 가지게 되었다. (Payment
의 로직 분리)
// src/Payment.tsx…
export const Payment = ({ amount }: { amount: number }) => {
// 이제부터 커스텀 훅 내부에서 상태를 가지게 되었다.
const { paymentMethods } = usePaymentMethods();
return (
<div>
<h3>Payment</h3>
<div>
{paymentMethods.map((method) => (
<label key={method.provider}>
<input
type="radio"
name="payment"
value={method.provider}
defaultChecked={method.provider === "cash"}
/>
<span>{method.label}</span>
</label>
))}
</div>
<button>${amount}</button>
</div>
);
};
하위 컴포넌트를 분리했다. 여기서는 PresentionalComponent
로 분할. 이렇게 하면 다음과 같은 이점을 얻는다.
<aside> 👉🏼 만약 컴포넌트를 순수 함수, 즉 입력이 주어지면 출력이 확실한 함수로 만들 수 있다면 테스트를 작성하고 코드를 이해하며 다른 곳에서 컴포넌트를 재사용하는 데 많은 도움이 될 것입니다. 결국 컴포넌트가 작을수록 재사용될 가능성이 높아집니다.
</aside>
/// src/Payment.tsx…
export const Payment = ({ amount }: { amount: number }) => {
const { paymentMethods } = usePaymentMethods();
return (
<div>
<h3>Payment</h3>
{/* 상태가 없는 순수한 함수로 분리했다. */}
<PaymentMethods paymentMethods={paymentMethods} />
<button>${amount}</button>
</div>
);
};
PaymentMethods
는 상태가 없는 순수 함수(순수 컴포넌트)라는 점에 유의하세요. 단순히 문자열을 포맷팅하는 함수입니다.