自作WebアプリでReactを学んでいく

はじめまして、ちまきと申します。

自作Webアプリの作成を通じて、Reactを自分なりに学習していきたいと思い、記事を書いています。

https://probable-computing-machine-g3ut.vercel.app/

なにを隠そうこの自作Webアプリ、生成AIによるコーディングということで　Claude3.7がほとんど生成してきたものになっています。
私はReact初心者のため、何が書いてあるか全く分かりませんでした。

全く分からないままというのも悔しいので、
少しずつ紐解いていきたいと思います。

自作Webアプリの内容は、IT技術学習アプリというもので
IT技術を4拓問題に解答する形式で知識を深めていくことができるものです。
![スクリーンショット 2025-05-05 153430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078294/a7e9ed94-7b30-4a1d-80b7-fafcc1ab611e.png)

テーマを選択すると、テーマに沿った問題が出題されて・・・
![スクリーンショット 2025-05-05 153448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078294/ac6341cb-4a9b-4c3f-bdc6-c75cff26e896.png)

正解・不正解や解説が表示されるものになっています。
![スクリーンショット 2025-05-05 153508.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4078294/8b9c4fee-3300-45e4-a8e6-800e7e076790.png)

ツリー構造としては、以下のようになっています。
project-root/
├── App.js                           # メインアプリケーションコンポーネント
├── pages/
│   ├── HelpPage.js                 # ヘルプページコンポーネント
│   ├── ChangeHistory.js            # 変更履歴ページコンポーネント
│   ├── ThemeSelection.js           # テーマ選択ページコンポーネント
│   └── QuestionPage.js             # 問題表示ページコンポーネント


Reactでは、状態管理という概念が重要であり、
useStateフックを使って初期状態が定義されています。

useStateはReactの「フック」（Hook）の一つです。フックは、React 16.8で導入された機能で、関数コンポーネントで状態やライフサイクルなどの機能を使えるようにするものだそうです。

```jsx:App.js
function App() {
  const [selectedTheme, setSelectedTheme] = useState(null);

```

これは
1.selectedThemeという状態変数を作成
2.その値を更新するためのsetSelectedTheme関数も作成
3.初期値としてnullを設定
という意味のようです。


では、状態を更新するための関数（setSelectedTheme）がコード上で
どのように出てくるかを見てみます。

```jsx:App.js
const selectTheme = (themeId) => {
  setSelectedTheme(themeId);
    setLoading(true);
  // ...残りのコード
};
```

これまた難しいですね・・・
どうやら、アロー関数という書き方のようです。

```
// アロー関数による定義
const 関数名 = (引数) => {
  // 処理
};
```

1.selectThemeはアプリケーション開発者（つまりは「ちまき」自身）が定義した関数
2.setSelectedThemeはReactから提供される状態更新関数
ということになります。

なぜ、selectThemeという関数が出てきたのでしょうか。これは以下の理由のようです。

```jsx:App.js
// 単純な状態更新ではなく複数の処理を行う例
const selectTheme = (themeId) => {
  setSelectedTheme(themeId);  // 状態更新①
  setLoading(true);          // 状態更新②
  // その他の処理...
};
```

単に状態を更新するだけでなく、複数の関連処理をまとめることで、コードの重複を減らし、処理の一貫性を保つ

selectTheme関数はApp.jsの子コンポーネントであるThemeSelectionコンポーネントの中で出てきます。
```jsx:ThemeSelection.js
<div 
  key={theme.id}
  className="border rounded-lg p-4 cursor-pointer hover:bg-gray-50 transition-colors"
  onClick={() => selectTheme(theme.id)}
>
```

各テーマのカードをクリックすると、そのテーマのIDを引数としてselectTheme関数が呼び出されます。

そして、selectTheme関数の中に包含されているsetSelectedTheme(themeId)が実行されると、
selectedThemeの値がthemeIdに更新される動きになるようです。

その後、selectedThemeの状態がどうなっているかでも
処理が異なってきます。

```jsx:App.js
  // メインコンテンツのレンダリング
  return (
    <div className="min-h-screen bg-orange-50">
      {selectedTheme ? (
        <QuestionPage 
          selectedTheme={selectedTheme}
          themes={themes}
          currentQuestion={currentQuestion}
          selectedAnswer={selectedAnswer}
          showExplanation={showExplanation}
          isCorrect={isCorrect}
          loading={loading}
          generatingQuestion={generatingQuestion}
          useGeneratedQuestions={useGeneratedQuestions}
          setSelectedTheme={setSelectedTheme}
          setShowHelp={setShowHelp}
          setShowChangeHistory={setShowChangeHistory}
          answerQuestion={answerQuestion}
          nextQuestion={nextQuestion}
          isTeacherKey={isTeacherKey}
        />
      ) : (
        <ThemeSelection 
          themes={themes}
          themeQuestions={themeQuestions}
          progress={progress}
          useGeneratedQuestions={useGeneratedQuestions}
          toggleQuestionMode={toggleQuestionMode}
          selectTheme={selectTheme}
          setShowHelp={setShowHelp}
          setShowChangeHistory={setShowChangeHistory}
        />
      )}
      
      {/* 生成中のオーバーレイ（常に最上位で表示） */}
      {renderGeneratingOverlay()}
    </div>
  );
}
```

これまた、分からないですが、
「三項演算子」というので書かれているようです。

```
条件 ? 条件が真の場合の値 : 条件が偽の場合の値
```

これはもっと簡単に書けば、
以下と同義のようです。

```
{
  if (selectedTheme) {
    return <QuestionPage ... />;
  } else {
    return <ThemeSelection ... />;
  }
}
```

条件部分: selectedTheme
1.JavaScriptでは、値がnull、undefined、0、""（空文字列）、false、NaNの場合は「偽」と評価されます
2.それ以外の値（文字列、数値、オブジェクトなど）は「真」と評価されます

条件が真の場合: <QuestionPage ... />
・selectedThemeが何らかの値（テーマID）を持っている場合、このコンポーネントがレンダリングされます

条件が偽の場合: <ThemeSelection ... />
・selectedThemeがnullまたはundefinedの場合、このコンポーネントがレンダリングされます

これによって、テーマが選択されている場合は、QuestionPageが
テーマが選択されていない場合は、ThemeSelectionが
表示されるという動きになります。



はじめての記事を書きましたが、色々理解や解説が微妙な部分もあるかなと思います。
今後の自作Webアプリ改善も通じて、理解を更に深めていきたいと思います。