Container・Presentationパターン
概要
フロントエンドのコンポーネントにおけるデザインパターン。
データ取得・副作用・アプリケーション状態の管理とUI表示の責務を分けることで関心の分離を実現する。
コンポーネントのパーツの再利用性を高めることができる。
使い方
bad
const UserProfile = () => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetchUser().then(setUser);
}, []);
if (!user) return <div>Loading...</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
};
表示と取得・状態が全部同じコンポーネントに集まってる。
取得ロジックのテストや状態管理のテストなどがやりにくい。
また、複雑化したときにコンポーネントが肥大化しやすい。
good
const UserProfileContainer = () => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
fetchUser().then(setUser);
}, []);
return <UserProfile user={user} />;
};
const UserProfile = ({ user }: { user: User | null }) => {
if (!user) return <div>Loading...</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
};
コンテナ: 状態や副作用、ロジックを持つコンポーネント プレゼンテーション: 状態や副作用、ロジックを持たないUI表示に特化したコンポーネント(厳密には、表示や見た目のためだけの状態は持っても良い)
使い所
UIとロジックを分けることで再利用性が上がる 状態を持たないため純粋にUIだけを評価できる → テストが書きやすくなる
- コンテナ: vitestなどのテストでロジックのテストが書きやすい
- プレゼンテーション: StorybookなどのテストでUIのテストが書きやすい
レイヤードアーキテクチャやDDDなどのプレゼンテーション層などとの違い
レイヤードアーキテクチャやDDDなどでもプレゼンテーション層などで表示とロジック(とその他)を分けているが、 それらとの違いは? → そもそも考えているスコープが違う
アーキテクチャの方がもっと広い → アプリケーション全体において ビジネスロジック と コード を繋ぎ合わせる
コンテナプレゼンテーションパターン → フロントのコンポーネントにおける表示とロジックの分離