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

[React] 超基本構造 EmailSender ( useState, event.currentTarget.value, <form>)

0
Posted at

概要

  • Vanilla JS と React を比較しながら、同じUIを異なる実装思想で構築する方法を解説
  • React における useState の基本的な使い方を整理
  • e.currentTarget.value を使って入力値を取得する方法を確認
  • コンポーネントの切り方・props の渡し方・import の方法を体系的に確認
  • 「命令的UI更新(Vanilla)」と「宣言的UI更新(React)」の違いをコードで比較

同じ「EmailSender」アプリを
Vanilla JS と React の両方で実装することで設計思想の違いを理解する


実施条件

  • React + Vite プロジェクトが構築済みであること
  • React Hooks(useState)の基本を理解していること
  • JavaScript のイベント処理の基礎理解があること

環境

ツール バージョン 目的
Node.js 22.5.1 実行環境
React 19.1.0 UI構築
Vite 5.x 開発サーバ
JavaScript ES2022 イベント処理

アプリ仕様(EmailSender)

  • メールアドレスを入力
  • 「Send」ボタン押下で送信完了メッセージ表示
  • 送信後は入力欄とボタンを無効化
  • Enterキーでも送信できる(formのsubmitとして扱う)

Vanilla JS 実装(命令的UI)

ディレクトリ構成

/vanilla-app
  ├── index.html
  └── index.js

index.html(<form> で input/button をまとめる)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>EmailSender (Vanilla)</title>
</head>
<body>
  <div>
    <!-- formにまとめることで Enter 送信(submit)を自然に扱える -->
    <form id="emailForm">
      <input
        id="emailInput"
        type="email"
        placeholder="email@example.com"
        required
      />
      <button id="sendButton" type="submit">Send</button>
    </form>

    <p id="message"></p>
  </div>

  <script src="index.js"></script>
</body>
</html>

index.js

// ============================
// DOM取得
// ============================

const emailFormEl = document.getElementById("emailForm");
const emailInputEl = document.getElementById("emailInput");
const sendButtonEl = document.getElementById("sendButton");
const messageEl = document.getElementById("message");

// ============================
// 状態
// ============================

let state = {
  email: "",
  submitted: false,
};

// ============================
// 状態更新
// ============================

function setState(partial) {
  state = { ...state, ...partial };
  render();
}

// ============================
// 画面更新
// ============================

function render() {
  // 入力欄の更新
  emailInputEl.value = state.email;
  emailInputEl.disabled = state.submitted;

  // ボタンの更新
  sendButtonEl.disabled = state.submitted || state.email === "";

  // メッセージの更新
  messageEl.textContent = state.submitted
    ? `送信しました: ${state.email}`
    : "";
}

// ============================
// イベント登録
// ============================

// 入力変更(emailのstate更新)
emailInputEl.addEventListener("input", (e) => {
  setState({ email: e.target.value });
});

// submit(ボタン押下でも Enter でもここに集約される)
emailFormEl.addEventListener("submit", (e) => {
  // formのデフォルト挙動(ページリロード)を止める
  e.preventDefault();

  // required や type="email" のHTML標準バリデーションが有効な場合、
  // 不正なら submit が発火しない(ブラウザがブロック)ことが多い

  setState({ submitted: true });
});

// 初期描画
render();

Vanillaの特徴

  • DOMを直接取得
  • 自分で状態管理
  • 自分で再描画関数を呼ぶ
  • UI更新はすべて命令的
  • <form> を使うことで submitイベントに統一できる(Enter送信も自然)

React 実装(宣言的UI)

ディレクトリ構成

/react-app
  ├── index.html
  ├── main.jsx
  ├── App.jsx
  └── components
        ├── EmailInput.jsx
        ├── SubmitButton.jsx
        └── Message.jsx

React Hooks の基本構造

  1. importセクション
  2. 型定義セクション
  3. 関数定義セクション
    3.1 内部状態管理セクション
    3.2 イベントハンドラーセクション
    3.3 副作用(useEffect)処理セクション
    3.4 返り値構築・ロジックセクション

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>EmailSender (React)</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/main.jsx"></script>
  </body>
</html>

main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

App.jsx(<form onSubmit> に変更)

// 1. importセクション
import { useState } from "react";
import EmailInput from "./components/EmailInput.jsx";
import SubmitButton from "./components/SubmitButton.jsx";
import Message from "./components/Message.jsx";

// 2. 型定義セクション
// 今回は不要

// 3. 関数定義セクション
export default function App() {

  // 3.1 内部状態管理セクション
  const [email, setEmail] = useState("");
  const [submitted, setSubmitted] = useState(false);

  // 3.2 イベントハンドラーセクション
  const handleSubmit = (e) => {
    // formのデフォルト挙動(ページリロード)を止める
    e.preventDefault();

    setSubmitted(true);
  };

  // 3.4 返り値構築・ロジックセクション
  return (
    <div>
      {/* formで包むことで Enter 送信も submit に統一できる */}
      <form onSubmit={handleSubmit}>
        <EmailInput
          value={email}
          disabled={submitted}
          onChange={setEmail}
        />

        {/* type="submit" にして submit として扱う */}
        <SubmitButton
          type="submit"
          disabled={submitted || email === ""}
        />
      </form>

      <Message
        submitted={submitted}
        email={email}
      />
    </div>
  );
}

components/EmailInput.jsx

// 1. importセクション
import React from "react";

// 3. 関数定義セクション
const EmailInput = ({ value, disabled, onChange }) => {

  // 3.2 イベントハンドラーセクション
  const handleChange = (e) => {
    // e.currentTarget.value を使用
    onChange(e.currentTarget.value);
  };

  // 3.4 返り値構築・ロジックセクション
  return (
    <input
      type="email"
      placeholder="email@example.com"
      value={value}
      disabled={disabled}
      required
      onChange={handleChange}
    />
  );
};

export default EmailInput;

components/SubmitButton.jsx(type を受け取れるように変更)

const SubmitButton = ({ disabled, type = "button" }) => {
  return (
    <button disabled={disabled} type={type}>
      Send
    </button>
  );
};

export default SubmitButton;

components/Message.jsx

const Message = ({ submitted, email }) => {
  return (
    <p>
      {submitted ? `送信しました: ${email}` : ""}
    </p>
  );
};

export default Message;

コンポーネントの切り方

Appは状態管理
子コンポーネントは表示責務のみ

コンポーネント 役割
App 状態管理・ロジック
EmailInput 入力UI
SubmitButton ボタンUI
Message 表示UI

propsの渡し方

親側

<EmailInput value={email} disabled={submitted} onChange={setEmail} />

子側

const EmailInput = ({ value, disabled, onChange }) => {}

import方法

import EmailInput from "./components/EmailInput.jsx";
  • export default の場合は好きな名前でimport可能

Vanilla vs React 比較

観点 Vanilla JS React
UI更新 手動DOM操作 state変更で自動再描画
状態管理 自前 useState
入力取得 e.target.value e.currentTarget.value
送信イベント form submit form onSubmit
コンポーネント なし 再利用可能

参考リンク

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