EY-Office ブログ

AIにReactコンポーネントを作ってもらいました、愉快愉快

AIシリーズ第3弾です、今回は画面画像からReactコンポーネントを作ってもらいまいました。
以前はデザイナーの方が作ってくれた画面画像を見ながら人力でRailsのViewを作ったり、過去に作られRailsアプリの画面を見ながらReactコンポーネントを作ったりしていましたが、やっとAIさんに登場してもらいました。

AIシリーズ

AI-code-generate Bing Image Creatorが生成した画像を使っています

課題

以前からReact教育で使っているNext.js + Tailwind CSSで作ったReactアプリのスクリーン・ショットを元にReactアプリを作ってもらいました。AIの環境は今までと同じく Cursor + Claude-3.5-sonnet です。

作品1

プロンプトは以下のように指定しました。

添付画像のようなReactコンポーネントを作ってください

# 環境は
- TypeScript
- スタイリングはTailwind CSS

生成された画面は以下です。

なぜか、グーのボタンを押すとグーの行だけ、パーのボタンを押すとパーの行だけが表示されコードが付加されています(表のフィルタリング機能でしょうか?)😁

  • コーディング・スタイルは良いですね ⭕
  • 対戦結果の型が定義されていますね ⭕
  • アプリケーション・バーのメニューが完全に無くなっていますね 😓
  • 対戦結果やジャンケンボタンのセンター合わせも無くなっていますね ❌
  • ボタンの色が違いますね ❌
  • テーブルの縦枠が無いですね ❌
  • 対戦結果表示の色の付き方が不思議ですね 😁
"use client";
import { useState } from "react";

export type Hand = 'グー' | 'チョキ' | 'パー';
export type Result = '勝ち' | '負け' | '引き分け';

export interface GameRecord {
  time: string;
  player: Hand;
  computer: Hand;
  result: Result;
}
export default function Home() {
  const [records, setRecords] = useState<GameRecord[]>([
    {
      time: '10:05:52',
      player: 'パー',
      computer: 'グー',
      result: '勝ち'
    },
    {
      time: '10:05:51',
      player: 'チョキ',
      computer: 'チョキ',
      result: '引き分け'
    },
    {
      time: '10:05:50',
      player: 'グー',
      computer: 'パー',
      result: '負け'
    }
  ]);

  const [selectedHand, setSelectedHand] = useState<Hand | null>(null);
  const filterButtons: Hand[] = ['グー', 'チョキ', 'パー'];

  return (
    <div className="p-4">
      <h1 className="text-2xl font-bold text-white bg-blue-600 p-4 mb-4">じゃんけんポン!</h1>

      <h2 className="text-xl mb-4">対戦結果</h2>

      <div className="flex gap-2 mb-4">
        {filterButtons.map((hand) => (
          <button
            key={hand}
            onClick={() => setSelectedHand(hand === selectedHand ? null : hand)}
            className={`px-4 py-2 rounded ${
              selectedHand === hand
                ? 'bg-blue-600 text-white'
                : 'bg-blue-100 text-blue-600'
            }`}
          >
            {hand}
          </button>
        ))}
      </div>

      <div className="overflow-x-auto">
        <table className="w-full border-collapse">
          <thead>
            <tr className="bg-gray-100">
              <th className="p-2 text-left">時間</th>
              <th className="p-2 text-left">人間</th>
              <th className="p-2 text-left">コンピュータ</th>
              <th className="p-2 text-left">結果</th>
            </tr>
          </thead>
          <tbody>
            {records
              .filter(record => !selectedHand || record.player === selectedHand)
              .map((record, index) => (
                <tr key={index} className="border-b">
                  <td className="p-2">{record.time}</td>
                  <td className="p-2">
                    <span className={record.result === '勝ち' ? 'text-red-500' : ''}>
                      {record.player}
                    </span>
                  </td>
                  <td className="p-2">
                    <span className={record.result === '負け' ? 'text-red-500' : ''}>
                      {record.computer}
                    </span>
                  </td>
                  <td className="p-2">{record.result}</td>
                </tr>
              ))}
          </tbody>
        </table>
      </div>
    </div>
  );

}

作品2

もう少し画面を正確にしてほしかったのでプロンプトは以下のようにしました。

添付画像のようなReactコンポーネントを作ってください

# 環境は
- TypeScript
- スタイリングはTailwind CSS
- 画面表示だけを作ってください

生成された画面は以下です。

今回は余分なコードは無いですね

  • コーディング・スタイルは良いですね ⭕
  • アプリケーション・バーのメニューが表示されました ⭕
  • しかし、表示位置が変ですね ❌
  • あいかわらずセンター合わせは出来ないですね ❌
  • ボタンの色が正しくなりました ⭕
  • 今度はテーブルの縦枠が表内部にもあります ❌
  • 対戦結果表示の色の付き方が良くなりましたがまだですね 😁
  • なぜかコンポーネントがアロー関数になりました 😁
"use client";
import React from 'react';

const Home: React.FC = () => {
  return (
    <div className="container mx-auto">
      {/* ヘッダー部分 */}
      <header className="bg-blue-600 text-white p-4">
        <h1 className="text-xl">じゃんけんポン!</h1>
        <div className="space-x-4">
          <span className="cursor-pointer">対戦結果</span>
          <span className="cursor-pointer">対戦成績</span>
        </div>
      </header>

      {/* メインコンテンツ */}
      <div className="p-4">
        <h2 className="text-lg mb-4">対戦結果</h2>

        {/* 手の選択ボタン */}
        <div className="flex gap-2 mb-4">
          <button className="bg-blue-500 text-white px-4 py-2 rounded">グー</button>
          <button className="bg-blue-500 text-white px-4 py-2 rounded">チョキ</button>
          <button className="bg-blue-500 text-white px-4 py-2 rounded">パー</button>
        </div>

        {/* 結果テーブル */}
        <table className="w-full border-collapse">
          <thead className="bg-gray-100">
            <tr>
              <th className="border p-2 text-left">時間</th>
              <th className="border p-2 text-left">人間</th>
              <th className="border p-2 text-left">コンピュータ</th>
              <th className="border p-2 text-left">結果</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td className="border p-2">10:05:52</td>
              <td className="border p-2">パー</td>
              <td className="border p-2 text-blue-600">グー</td>
              <td className="border p-2 text-blue-600">勝ち</td>
            </tr>
            <tr>
              <td className="border p-2">10:05:51</td>
              <td className="border p-2">チョキ</td>
              <td className="border p-2">チョキ</td>
              <td className="border p-2">引き分け</td>
            </tr>
            <tr>
              <td className="border p-2">10:05:50</td>
              <td className="border p-2 text-red-600">グー</td>
              <td className="border p-2 text-red-600">パー</td>
              <td className="border p-2 text-red-600">負け</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default Home;

まとめ

今回、画像からReactコンポーネントを生成してもらいましたが感想は、ここまで出来るのか! と同時に こんなものか? です。

たぶんプロンプトに色々書けばもう少し良いコードになりそううな気がしますが、中央揃えが全く出来ないとか、対戦結果の表の単純な色付けが上手く行かないとか不思議ですね。 マルチモーダルに対応しているとはいえ、認識した画像をLLMで処理する際には情報が落ちてしまうのでしょうか?
今回のように正確な画面画像を作っても、AIにお任せにはならないですね。

ただし、現在のレベルでもコーディングの助けになるのは確かですね。😊

DeepSeek-R1が強化学習を使って能力を上げている事が話題になってしますね。正解(1つではありませんが)があるプログラミングの能力を鍛えるのは、それほど難しくないのかも知れませんね。ネット上には良質なオープンソース・ソフトウェアが豊富にあり、それをコンピューター上で動かせるのでプログラミングの能力は、今後さらに高まりそうですね。

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ