Container/Presentationalパターンとは
Container/Presentationalパターン(以下:C/Pパターン)とは、
ロジック層(Container)と表示層(Presentational)を分離する設計パターンです。
Containerがデータ取得や状態管理を担当し、Presentationalは受け取ったpropsを表示するだけという構成になります。
主なメリットは、以下の通りです。
- 複雑なロジックをUIと分離できる
- ロジックのテストがしやすい
ただ、このパターンはすでに古いもので、フックの登場によって廃れていきました。
フック登場後の変化
フックの登場により、関数コンポーネントで状態管理ができるようになりました。
(https://ja.react.dev/reference/react/hooks)
以前はクラスコンポーネントでしか状態を持てなかったため、C/Pパターンが有用でしたが、
今は関数コンポーネントだけで完結できます。
C/Pパターンを提唱したDan氏も言っている通り、無理に使う必要性はないでしょう。
(https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0)
まだ有効なユースケース
PC/SPでUIを出し分ける場合、同じロジックを使うならC/Pパターンが有効なのではと思います。
理由は、ロジックをContainerに集約することでDRY原則を守れる(重複コードを減らせる)ためです。
PC/SP各コンポーネントにロジックを持たせた場合
const PCForm = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = async () => {
await post({ name, email });
};
return ( {/* PC用UI */} );
};
const SPForm = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = async () => {
await post({ name, email });
};
return ( {/* SP用UI */} );
};
C/Pパターンを活用して共通化した場合
// Container
const UserFormContainer = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = async () => {
await post({ name, email });
};
const props = { name, setName, email, setEmail, handleSubmit };
if (isMobile) {
return <SPForm {...props} />;
}
return <PCForm {...props} />;
};
// Presentational
const PCForm = ({ name, setName, email, setEmail, handleSubmit }) => (
{/* PC用UI */}
);
const SPForm = ({ name, setName, email, setEmail, handleSubmit }) => (
{/* SP用UI */}
);
明確に同じロジック(PC/SPで差異が出る予定もなさそう)であれば、
まとめてしまった方が管理しやすいですね。
まとめ
結果論的ではありますが、、、
PC/SPの出し分けなど、複数のコンポーネントで同じロジックを使う場合は、
部分的にC/Pパターンの形式を活かせそうです。
PC/SPで共通していないものは、各コンポーネントに書いてあげると読みやすいコードになりそうですね。
(ただのDRY原則の話になってる気がしますが、これはこれで笑)