Study Log

日々の学習のまとめ・備忘録

View on GitHub
9 December 2025

Reactでパスワードを生成する

by Natsumi Chiba

Reactでパスワードを生成します
各コードがどの様な動きをしているかコメントアウト付きです

// React コンポーネントを画面に描画するためのライブラリ
import ReactDOM from 'react-dom'
// React 本体と useState フックを読み込む
import React, { useState } from 'react'

function App() {
  // 生成されたパスワードを保持する state
  const [password, setPassword] = useState('')

  // パスワード生成関数
  // length・hasNumbers・hasSymbols をオブジェクトで受け取る
  const generatePassword = ({
    length = 12,         // パスワードの長さ(デフォルト12)
    hasNumbers = true,   // 数字を含めるか
    hasSymbols = true    // 記号を含めるか
  }) => {
    // 各文字セットを定義
    const alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    const numbers = '0123456789'
    const symbols = '!@#$%^&*_-+='

    // まずは英字をベースにする
    let chars = alpha

    // ユーザーが選択していれば数字を追加
    if (hasNumbers) {
      chars += numbers
    }

    // 記号を含める場合は追加
    if (hasSymbols) {
      chars += symbols
    }

    // ランダムに選んでパスワードを作る
    let newPassword = ''
    for (let i = 0; i < length; i++) {
      // chars の中からランダムに1文字取り出す
      newPassword += chars[Math.floor(Math.random() * chars.length)]
    }

    // state に新しいパスワードを保存 → 画面が更新される
    setPassword(newPassword)
  }

  return (
    <div>
      <h1>パスワードジェネレーター</h1>

      {/* 現在のパスワードを表示 */}
      <p>{password}</p>

      {/* 子コンポーネントに関数を渡す(props) */}
      <PasswordForm generatePassword={generatePassword} />
    </div>
  )
}

function PasswordForm({ generatePassword }) {
  // フォームの入力状態をまとめて管理する state
  const [passwordData, setPasswordData] = useState({
    length: 12,       // パスワードの長さ
    hasNumbers: true, // 数字を含める
    hasSymbols: true  // 記号を含める
  })

  // フォーム送信時の処理
  const handleSubmit = (event) => {
    event.preventDefault() // ページリロードを防ぐ
    generatePassword({ ...passwordData }) // 親の生成関数へデータを渡す
  }

  return (
    <form onSubmit={handleSubmit}>
      {/* パスワードの長さ選択(ラジオボタン) */}
      <label>
        パスワードの長さ:
        <label>
          <input
            type="radio"
            value="12"
            name="length"
            // 選択状態のチェック
            checked={passwordData.length === 12}
            // 入力変化時に state を更新
            onChange={(event) =>
              setPasswordData({
                ...passwordData,                // 既存の値を保持
                length: parseInt(event.target.value) // 新しい length
              })
            }
          />
          12
        </label>

        <label>
          <input
            type="radio"
            value="24"
            name="length"
            checked={passwordData.length === 24}
            onChange={(event) =>
              setPasswordData({
                ...passwordData,
                length: parseInt(event.target.value)
              })
            }
          />
          24
        </label>
      </label>

      <br />

      {/* 数字を含めるかどうか(チェックボックス) */}
      <label>
        数字を含める:
        <input
          type="checkbox"
          checked={passwordData.hasNumbers}
          onChange={(event) =>
            setPasswordData({
              ...passwordData,
              hasNumbers: event.target.checked // true/false を受け取る
            })
          }
        />
      </label>

      <br />

      {/* 記号を含めるかどうか(チェックボックス) */}
      <label>
        記号を含める:
        <input
          type="checkbox"
          checked={passwordData.hasSymbols}
          onChange={(event) =>
            setPasswordData({
              ...passwordData,
              hasSymbols: event.target.checked
            })
          }
        />
      </label>

      <br />

      {/* パスワード生成ボタン */}
      <button type="submit">生成</button>
    </form>
  )
}

// App を #root に描画する
ReactDOM.createRoot(document.getElementById('root')).render(<App />)

ポイント

✔ generatePassword に設定項目をまとめて渡している
generatePassword({ length, hasNumbers, hasSymbols })
こうすることで 複数の設定を 1 つのオブジェクトで扱える
→ コードがスッキリして拡張もしやすい。

✔ パスワード生成はランダム選択を繰り返すだけ
chars[Math.floor(Math.random() * chars.length)]

✔ 子コンポーネントから親の関数を呼ぶ
<PasswordForm generatePassword={generatePassword} />
React でとてもよく使うパターン

tags: