2
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?

GitHub Copilotで、ReactのuseStateを完全に理解した

Last updated at Posted at 2025-01-05

はじめに

これの続きです。

STEP

要件整理(画面デザイン作成) 
・フロンドエンド開発
 ・静的画面
 ・表示切り替え(useState)  ←いまここ
 ・画面遷移(useRouter)
 ・APIモック作成
・バックエンド開発

今回のやることとゴール

このSTEPではひとつ前の工程作成したログイン画面に
ログイン画面とアカウント登録画面の切り替え(useState)処理を実装してみたいと思います。

目次

1. 表示切替処理を追加
2. テストレコードの作成
3. 子コンポーネントにuseStateを渡す

開発開始

ログイン画面とアカウント登録画面の切り替え(useState)

完成画面イメージ

ログイン画面はこちら

image.png

「新規作成はこちら」をクリックした際の画面はこちら
システムタイトルは固定で入力テキストボックスのエリアが切り替わります。

image.png

ルートページのコード

page.tsx
'use client'

import LoginForm from './login/page'

export default function Home() {

  return (
    <div className="min-h-screen bg-gray-100 flex items-center justify-center p-4 font-noto-sans">
      <div className="bg-white rounded-lg shadow-lg p-8 w-full max-w-md">
        <h1 className="text-2xl font-bold text-center mb-8 text-gray-800">
          連絡帳システム
        </h1>
        <LoginForm />
      </div>
    </div>
  )
}

表示切替処理を追加

ルートページファイルをCopilotの編集に追加

image.png

以下呪文を唱える

React の useState フックを使用して、ビュー(画面表示)の状態を管理してください。

ログイン状態の場合、
LoginFormコンポーネントを表示し、

アカウント登録状態の場合、
LoginFormコンポーネントを非表示にして、固定文字「アカウント登録ページは準備中>です」を表示したいです。
またその文字の下にはログイン状態に戻す用のリンクを表示してください。

image.png

動作確認

テスト用のボタンを追加して動作確認します。

image.png

Toggle to Loginリンクをクリック

image.png

ちゃんと表示が切り替わりました。

image.png

ログインページに戻るボタンも動作しました。

image.png

テストレコードの作成

コードは生成できましたが、うまくファイルを新規作成できませんでした。
手動でファイルを保存してください。
またエラーが出た場合は、Copilotに質問しながら解消します。

image.png

自動生成されたコードは以下

今回自動生成したファイルには、モック化とimportしたコンポーネントの辻褄が合わない箇所がありますが、
必要に応じて修正してください。

page.test.tsx

import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import Home from './page'
import LoginForm from './login/page'

jest.mock('./login/page', () => {
    return jest.fn(() => <div data-testid="mock-login-form">Login Form</div>)
})

describe('Home component', () => {
    it('renders heading text', () => {
        render(<Home />)
        expect(screen.getByText('連絡帳システム')).toBeInTheDocument()
    })

    it('shows login form by default', () => {
        render(<Home />)
        expect(screen.getByTestId('mock-login-form')).toBeInTheDocument()
    })

    it('toggles between login and register views', () => {
        render(<Home />)
        
        // Click toggle button to show register view
        fireEvent.click(screen.getByText('Toggle to Login'))
        expect(screen.getByText('アカウント登録ページは準備中です')).toBeInTheDocument()
        
        // Click back to login button
        fireEvent.click(screen.getByText('ログインページに戻る'))
        expect(screen.getByTestId('mock-login-form')).toBeInTheDocument()
    })
})

テストレコードの意味を解説してもらいましょう。

ファイル内のコードを全選択するか、
@workspace /explain で対象ファイルを設定します。

image.png

image.png

image.png

実行してみます

npx jest src/app/page.test.tsx

image.png

エラーになったので、Copilotに質問します。

修正方法を教えてくれたので、実行します。

image.png

通るようになりました。

image.png

子コンポーネントにuseStateを渡す

テスト用の「Toggle to Login」を削除し、
「新規登録はこちら」リンクから画面の切り替えができるようにします。

子コンポーネントを選択して、Ctrl+I で追加します。
(この依頼ができるなら手で追加した方が速そうだけどw)

image.png

子コンポーネント側を修正します。

エラー箇所から追加できないか色々試しましたが、今時点その修正方法はできないようでした。
明示的にpropsの追加を依頼してください。

追加した引数を追加してもらいます。

image.png

修正されました。

image.png

※Dispatchはわからない。この方の記事を読んでみなさんは理解してください。

親コンポーネントで引数を追加した際に、対象リンクを指定したので、ボタンクリック処理も修正されていました。

image.png

動作確認

キャプチャは省略しますが、
「新規登録はこちら」リンクをクリックして、ちゃんと表示が切り替わりました。
ログインページに戻るボタンも動作しました。

テスト再実行

TODO

めっちゃ書き換わっちゃったので、追っていい感じになったら記事更新します。

まとめ

たたき台をAIに作ってもらって、そのコードの意味を質問したり調べたりして、
妥当なコードを採用し、意味を理解しながら進めるとよいと思います。

2
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
2
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?