Open4

Atomic Designのメモ

shunshun

フロントエンド開発の悩みどころ

フロントエンド開発をしていると

  • コンポーネントのpropsにどういうデータを渡すべきか
  • どの粒度でコンポーネントを分けるか
    が意見の分かれどころ

見た目と振る舞いを分ける

フロントエンド開発に合ったっては「見た目」と「振る舞い」を分離することで、それぞれのコンポーネントの責務が明確になり、意見が分かれにくくなる。

その結果、開発効率が上がる、テストやデバッグが簡単になる、保守性が高まる、といったメリットがある。

「見た目」をPresentational Component、「振る舞い」をContainer Component として一般的に呼ばれる。

Presentational Componentの責務

  • 基本的にはpropsから渡されたデータを元にデザインを実装するだけ
  • propsからデータを受け取り、それぞれのコンポーネントに割り振る
  • classNameなどを指定してスタイルを適用する
  • 状態を持たない
  • APIを呼び出さない

propsにのみ依存することで、同じpropsに対して常に同じものが表示されるようにでき、デザインのデバッグが楽になる

Presentational Componentの例

import "./styles.css";

type ButtonProps = {
  label: string;
  text: string;
  disabled: boolean;
  onClick: React.MouseEventHandler<HTMLButtonElement>;
};

export const Button = (props: ButtonProps) => {
  const { label, text, disabled, onClick } = props;

  return (
    <div className="button-container">
      <span>{label}</span>
      <button disabled={disabled} onClick={onClick}>
        {text}
      </button>
    </div>
  );
};
shunshun

Container Componentの責務

  • デザインは実装せず、ロジックのみを書く
  • Hooksを持たせ、APIを実行する
  • コンポーネントの振る舞い(ボタンをいつ無効化するか、ボタンを押した時の挙動はどうするか、など)
import { useState, useCallback } from "react";
import { Button } from "./ButtonPresentation";

type CountButtonProps = {
  label: string;
  max: number;
};

export const CountButton = (props: CountButtonProps) => {
  const { label, max } = props;
  const [count, setCount] = useState(0);

  const onClick = useCallback(() => {
    const newCount = count + 1;
    setCount(newCount);
  }, [count, max]);

  const disabled = count >= max;
  const text = disabled ? `もう押せません` : `${count}回クリックしました`;

  return (
    <div>
      <Button label={label} text={text} disabled={disabled} onClick={onClick} />
    </div>
  );
};
shunshun

Presentation と Container のイメージ

  • イメージ

    ItemPageContainer
      |--- props ---> ButtonPresentation
      |--- props ---> SearchPresentation
      |--- props ---> ItemPresentation
    
  • Containerが親としてロジックを組む

  • Presentationが子としてpropsを使って画面を作る

shunshun

Atomic Design

5つの階層に分けてデザインを定義

階層 説明
Atoms 最小の要素 ボタン、テキスト
Molecules 複数のAtomsを組み合わせ 検索フォームなど。1つの役割を持ったUIのみを実装する
Organisms Moleculesよりも具体的な要素 ヘッダー、フッター、サイドバー、ボディーなど。ロジックはContainer Component、見た目はPresentational Componentに分けて実装する
Templates ページ全体のレイアウト ワイヤフレームのようなイメージ。Organismを組み合わせてCSSでレイアウトしていく
Pages ページそのもの コンテンツ、データを含めたページ要素全て。状態管理、ルーティング、API処理などを実装する

以下のサイトで、違いが分かりやすく纏まっている
https://design.dena.com/design/atomic-design-を分かったつもりになる