5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ミライトデザインAdvent Calendar 2024

Day 16

2024年 お世話になった React ライブラリをざっくり紹介

Posted at

ミライトデザイン Advent Calendar 2024 16日目の記事になります。

15日目は takuma さんの 「DynamoDB 全くわからないのでまとめてみた」の記事でした。

私も DynamoDB 全くわからない勢ですが、
RDBと比べて設計の考え方が全然違うんだなと感じました。
とても参考になりました!

はじめに

現在、私は React を使用したプロジェクトに携わっています。
2024年も残りわずかとなり、今年お世話になったライブラリを振り返ってみることにしました。

目的

プロジェクトでは、自分以外のメンバーが導入したライブラリも多くあります。
そのため、これらのライブラリについて調べ、実際に試してみて、使い方をざっくり理解したいと考えています。

今回は、その中で紹介しやすかったり、便利だと思った5つのライブラリを紹介します。

ライブラリ紹介について

以下の構成で説明を進めます。

  • 実現したいこと
  • ライブラリ名
  • ライブラリ概要

実現したいこと: UI コンポーネントを効率的に構築したい

ライブラリ名: Chakra UI

ライブラリ概要

Chakra UIとは、React ベースの UI コンポーネントライブラリの一つで、
開発者が簡単かつ効率的にモダンな UI を構築できるよう設計されています。
特に、スタイルとテーマのカスタマイズが容易なため、デザインの一貫性を保ちながら柔軟な対応が可能です。

例として以下のようなデザインを作成してみます。

image.png

実装例

const Component = () => {
  return (
    <Box
      maxW="sm"
      borderWidth="1px"
      borderRadius="lg"
      overflow="hidden"
      p={6}
      bg="white"
      boxShadow="md"
    >
      <Image src="./images/cat1.jpeg" alt="Sample Image" />

      <Box mt={4} textAlign="center">
        <Text fontWeight="bold" fontSize="xl">
          サンプルカード
        </Text>
        <Text mt={2} color="gray.600">
          Chakra UI を使って簡単なレイアウトを作成してみる。
        </Text>
        <HStack spacing={8} justifyContent="center" p={4} mt={4}>
          <VStack spacing={2} align="center">
            <Text fontWeight="bold" fontSize="md" color="teal.500">
              サンプル1
            </Text>
            <Text fontSize="sm" color="gray.600">
              説明テキスト1
            </Text>
          </VStack>
          <VStack spacing={2} align="center">
            <Text fontWeight="bold" fontSize="md" color="teal.500">
              サンプル2
            </Text>
            <Text fontSize="sm" color="gray.600">
              説明テキスト2
            </Text>
          </VStack>
        </HStack>
        <Button colorScheme="teal" mt={6} leftIcon={<FaCat />}>
          ボタン
        </Button>
      </Box>
    </Box>
  );
};

いくつか特徴を挙げます

  • 豊富なコンポーネント
    • ボタン、入力フィールド、モーダル、カードなど、日常的によく使用される基本コンポーネントが多数用意されています
  • レイアウトの容易さ
    • クラス名を考える必要がなく、レイアウト用のコンポーネント(例: HStack, VStack)を使えば簡単に配置ができます
  • スタイルのショートハンド
    • p={6}, mt={4} などの簡潔なスタイル指定が可能です
  • カスタムテーマ機能
    • デフォルトのテーマをベースに、独自の色やフォントを簡単に設定できます
    • ブランドカラーやフォントサイズなどを指定したり、コンポーネントのスタイルを上書きすることが可能です
    • 参考記事はこちら

※React の UI コンポーネントライブラリは、Chakra UI の他にも Material-UI, React Bootstrap など多く存在しますが、今回は Chakra UI に限定して紹介しました。

実現したいこと: 棒(円)グラフを描きたい

ライブラリ名: recharts

ライブラリ概要

データの視覚化に便利なライブラリです。
例えば、以下のような「男女の年代比率」や「家計簿管理での収支のカテゴリ比率」を簡単に表示できます。

image.png

実装例:年代比率の棒グラフ

const data = [
  { name: "〜20代", value: 10 },
  { name: "30代", value: 40 },
  { name: "40代", value: 30 },
  { name: "50代〜", value: 5 },
];

const Component = () => {
  return (
    <Box p={4} boxShadow="md" mt={6}>
      <Heading as={"h3"} className="chart-heading" fontSize={"lg"} mb={3}>
        年代比率
      </Heading>
      <ResponsiveContainer width="100%" height={200}>
        {/* 棒グラフを表示するコンポーネント */}
        <BarChart data={data}>
          {/* グラフ背景の線を表示するグリッド */}
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis tickLine={false} dataKey="name" />
          <YAxis
            tickLine={false}
            type="number"
            tickFormatter={(value) => `${value}%`}
          />
          {/* 実際のデータを棒グラフとして描画 */}
          <Bar dataKey="value" fill="#DF6160" barSize={30} />
        </BarChart>
      </ResponsiveContainer>
    </Box>
  );
};

必要なデータがあれば、棒グラフ (BarChart) を簡単に作成できます。
また、棒グラフだけでなく、円グラフなら PieChart コンポーネントを使用できます。

実現したいこと: 画像一覧から写真を選択・拡大表示し、次の写真に移動させたい

ライブラリ名: yet-another-react-lightbox

ライブラリ概要

写真の拡大表示に加え、次の写真への移動が必要なため適したライブラリを検討しました。
候補はlightbox-reactyet-another-react-lightboxの2つでしたが、ダウンロード数と更新頻度の比較から後者を選択しました。

ダウンロード数比較はこちら

機能説明

  • 画像をクリックすると、モーダルとして拡大表示されます
  • モーダル内では矢印ボタンで次の画像に移動可能
  • 閉じるボタンで元の画面に戻ります

※公式サンプルでは、ボタンでモーダルを開く例の記述がありましたが、
この記事では画像クリックでモーダルを開くように実装しています。

lightbox.gif

実装例

// 表示する画像の配列
const images = [
  "cat1.jpeg",
  "cat2.jpeg",
  "cat3.jpeg",
  "cat4.jpeg",
  "cat5.jpeg",
  "cat6.jpeg",
];

const Component = () => {
  const [isOpen, setIsOpen] = useState(false); // Lightboxの表示状態
  const [currentIndex, setCurrentIndex] = useState(0); // 現在表示している画像のインデックス

  // 画像クリック時の処理
  const handleClick = (index) => {
    setCurrentIndex(index);
    setIsOpen(true);
  };

  return (
    <Box p={4} mt={50} mb={150}>
      {/* 画像一覧のグリッド表示 */}
      <SimpleGrid columns={2} spacing={4}>
        {images.map((src, index) => (
          <Image
            key={index}
            src={`./images/${src}`}
            alt={`image-${index}`}
            cursor="pointer"
            onClick={() => handleClick(index)}
            borderRadius="md"
            boxShadow="md"
          />
        ))}
      </SimpleGrid>
      
      {/* Lightbox モーダル */}
      <Lightbox
        open={isOpen} // モーダルの開閉状態
        index={currentIndex} // 現在表示している画像インデックス
        close={() => setIsOpen(false)}
        slides={images.map((image) => ({
          src: `./images/${image}`,
          alt: "image",
        }))}
      />
    </Box>
  );
};

実現したいこと: 画面のスクロールに応じた要素の表示制御

ライブラリ名: react-intersection-observer

ライブラリ概要

フォーム登録ページでは、「登録ボタン」を固定フッターとして画面下部に表示していました。
しかし、ページの最下部までスクロールすると、最下部の要素が登録ボタンに隠れてしまう問題が発生。

そこで、画面のスクロール位置に応じて、最下部の登録ボタンが表示されたタイミングで固定フッターの登録ボタンを非表示にするよう調整しました。

機能説明

  • 最初は固定フッターの「登録ボタン1」が表示されています
  • 画面下部の「登録ボタン2」が表示されたタイミングで固定フッター(登録ボタン1)が非表示になり、下部の要素が隠れないようになります

イメージ
IntersectionObserver.gif

実際例:コード

const Component = ({ className }) => {
  // ref: 監視対象の要素参照
  // inView: 監視対象が画面内に入っているかどうかの判定フラグ
  const [ref, inView] = useInView({
    threshold: 0.1, // 要素の10%以上が表示されたときに検知
  });

  return (
    <div className={className}>
      <div className="content">
        <div className="section">セクション 1</div>
        <div className="section">セクション 2</div>
        <div className="section">セクション 3</div>
        <div className="section">セクション 4</div>
        {/* 監視されているボタン */}
        {/* refを与えた要素がウインドウ内に現れるとinViewがtrueになる */}
        {!inView && <div className="fixed-button">固定の登録ボタン</div>}
        {/* 監視対象のボタン */}
        <button ref={ref} className="button">
          登録
        </button>
        <div className="section">フッター</div>
      </div>
    </div>
  );
};

実現したいこと: 画像をカルーセル表示したい

ライブラリ名: embla-carousel-react

ライブラリ概要

画像をカルーセル形式で表示するために使用したライブラリです。
カルーセルは、限られたスペースで多くの画像を見せたい場合などに有効ですね。

ユーザーはボタンや画像のサムネイルをクリックすることで、
スライドを切り替えることができます。

また、画像の枚数を(2/10など)表示したり、自動で画像が切り替わるような設定も可能です。

slider.gif

実際のコード例(スタイルは省略)

// 表示する画像リスト
const images = [
  "cat1.jpeg",
  "cat2.jpeg",
  "cat3.jpeg",
  "cat4.jpeg",
  "cat5.jpeg",
  "cat6.jpeg",
];

const Component = ({ className }) => {
  // emblaRef: スライダーの DOM 要素に関連付ける参照 (ref)。
  // emblaApi: スライダー操作用の API オブジェクト。スライドの移動、状態管理に使用する
  const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }); // スライダーの無限ループを有効にする
  // 前のスライドへ移動
  const onPrevButtonClick = useCallback(() => {
    if (!emblaApi) return;
    emblaApi.scrollPrev();
  }, [emblaApi]);
  
  // 次のスライドへ移動
  const onNextButtonClick = useCallback(() => {
    if (!emblaApi) return;
    emblaApi.scrollNext();
  }, [emblaApi]);

  return (
    <div className={className}>
      <div className="slider">Slider</div>
      {/* スライダー本体 */}
      <div className="embla" ref={emblaRef} style={{ overflow: "hidden" }}>
        <div className="embla__container" style={{ display: "flex" }}>
          {images.map((src, index) => (
            <div
              className="embla__slide"
              key={index}
              style={{ flex: "0 0 100%" }}
            >
              <img
                src={`./images/${src}`}
                alt={`Slide ${index + 1}`}
                style={{ width: "100%", height: "auto" }}
              />
            </div>
          ))}
        </div>
      </div>
      {/* スライド操作ボタン */}
      <div className="embla__controls">
        <div className="embla__buttons">
          <button onClick={onPrevButtonClick}>Prev</button>
          <button onClick={onNextButtonClick}>Next</button>
        </div>
      </div>
    </div>
  );
};

さいごに

この記事では5つの React ライブラリを紹介しました。

本当はもっと多くのライブラリを紹介する予定だったのですが、
調べたり整理するのに予想以上に時間がかかってしまい、紹介しきれませんでした。

また機会があれば、別の記事で他のライブラリも紹介したいと思います。

この記事がきっかけで、新たに使い始めるライブラリが見つかれば嬉しいです!

明日は、yuki さんの記事です。
よろしくお願いします!

参考

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?