# สัปดาห์ที่ 12 - React #2: useState & Events

## สารบัญ

1. [useState Hook - จัดการ State](#usestate-hook---จัดการ-state)
   - [State คืออะไร](#state-คืออะไร)
   - [ตัวอย่างเปรียบเทียบ](#ตัวอย่างเปรียบเทียบ)
   - [วิธีใช้ useState](#วิธีใช้-usestate)
   - [ตัวอย่าง 1: Counter](#ตัวอย่าง-1-counter)
   - [ตัวอย่าง 2: Toggle](#ตัวอย่าง-2-toggle-เปิดปิด)
   - [ตัวอย่าง 3: State ที่เป็น Object](#ตัวอย่าง-3-state-ที่เป็น-object)

2. [Event Handling - ตอบสนองต่อเหตุการณ์](#event-handling---ตอบสนองต่อเหตุการณ์)
   - [Event พื้นฐาน](#event-พื้นฐาน)
   - [ตัวอย่าง 1: Simple Click](#ตัวอย่าง-1-simple-click)
   - [ตัวอย่าง 2: Input Text](#ตัวอย่าง-2-input-text)
   - [ตัวอย่าง 3: Form Submit](#ตัวอย่าง-3-form-submit)

3. [Form Inputs - Controlled Components](#form-inputs---controlled-components)
   - [Controlled Components](#controlled-components)
   - [ตัวอย่าง](#ตัวอย่าง)

4. [Conditional Rendering - แสดงผลตามเงื่อนไข](#conditional-rendering---แสดงผลตามเงื่อนไข)
   - [ตัวอย่าง 1: Ternary Operator](#ตัวอย่าง-1-ternary-operator)
   - [ตัวอย่าง 2: Logical AND](#ตัวอย่าง-2-logical-and)
   - [ตัวอย่าง 3: Status Display](#ตัวอย่าง-3-status-display)

5. [ตัวอย่าง Todo App](#ตัวอย่าง-todo-app)

6. [สรุปสัปดาห์ที่ 12](#สรุปสัปดาห์ที่-12)

7. [สัปดาห์หน้า](#สัปดาห์หน้า)

---

## useState Hook - จัดการ State

บทนี้จะศึกษาวิธีให้ Component จำข้อมูลได้ และเปลี่ยนแปลงได้เมื่อผู้ใช้โต้ตอบ เช่น การนับเพิ่ม/ลด การเปิด/ปิดเมนู หรือการบันทึกรหัสผ่าน

### State คืออะไร

**State** คือข้อมูลที่ Component จำได้ และสามารถเปลี่ยนแปลงได้ เมื่อ State เปลี่ยน React จะอัปเดต UI โดยอัตโนมัติ

### ตัวอย่างเปรียบเทียบ

```javascript
// ตัวแปรธรรมดา - UI ไม่อัปเดต
let count = 0;
function increment() {
  count++; // console จะแสดงค่าใหม่ แต่ UI ไม่เปลี่ยน
}

// useState - UI อัปเดตโดยอัตโนมัติ
import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  function increment() {
    setCount(count + 1); // UI อัปเดต!
  }
}
```

### วิธีใช้ useState

```javascript
import { useState } from "react";

export default function Counter() {
  // ประกาศ State
  const [count, setCount] = useState(0);
  //     ↑      ↑                 ↑
  //   ค่า   ฟังก์ชันเปลี่ยน   ค่าเริ่มต้น

  return (
    <div>
      <p>จำนวน: {count}</p>
      <button onClick={() => setCount(count + 1)}>เพิ่ม</button>
    </div>
  );
}
```

### ตัวอย่าง 1: Counter

```javascript
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div style={{ textAlign: "center", padding: "20px" }}>
      <h1>ตัวนับ</h1>
      <p style={{ fontSize: "36px", color: "#007bff" }}>{count}</p>
      <div style={{ gap: "10px", display: "flex", justifyContent: "center" }}>
        <button onClick={() => setCount(count - 1)}>ลด</button>
        <button onClick={() => setCount(0)}>รีเซ็ต</button>
        <button onClick={() => setCount(count + 1)}>เพิ่ม</button>
      </div>
    </div>
  );
}
```

### ตัวอย่าง 2: Toggle (เปิด/ปิด)

```javascript
import { useState } from "react";

export default function ToggleMenu() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>
        {isOpen ? "ปิดเมนู" : "เปิดเมนู"}
      </button>

      {isOpen && (
        <div
          style={{
            backgroundColor: "#f0f0f0",
            padding: "20px",
            marginTop: "10px",
            borderRadius: "4px",
          }}
        >
          <p>
            <a href="#home">หน้าแรก</a>
          </p>
          <p>
            <a href="#about">เกี่ยวกับ</a>
          </p>
          <p>
            <a href="#contact">ติดต่อ</a>
          </p>
        </div>
      )}
    </div>
  );
}
```

### ตัวอย่าง 3: State ที่เป็น Object

```javascript
import { useState } from "react";

export default function UserInfo() {
  const [user, setUser] = useState({
    firstName: "",
    lastName: "",
    age: "",
  });

  // วิธีถูก: spread operator
  function updateFirstName(newName) {
    setUser({ ...user, firstName: newName });
  }

  function updateLastName(newName) {
    setUser({ ...user, lastName: newName });
  }

  function updateAge(newAge) {
    setUser({ ...user, age: newAge });
  }

  return (
    <div>
      <h2>ข้อมูลส่วนตัว</h2>
      <input
        value={user.firstName}
        onChange={(e) => updateFirstName(e.target.value)}
        placeholder="ชื่อ"
      />
      <input
        value={user.lastName}
        onChange={(e) => updateLastName(e.target.value)}
        placeholder="นามสกุล"
      />
      <input
        value={user.age}
        onChange={(e) => updateAge(e.target.value)}
        placeholder="อายุ"
        type="number"
      />

      <h3>ข้อมูลที่บันทึก:</h3>
      <p>
        ชื่อ: {user.firstName} {user.lastName}, อายุ: {user.age}
      </p>
    </div>
  );
}
```

---

## Event Handling - ตอบสนองต่อเหตุการณ์

บทนี้จะศึกษาวิธีทำให้ Component ตอบสนองต่อสิ่งที่ผู้ใช้ทำ เช่น คลิกปุ่ม พิมพ์ข้อความ หรือส่งฟอร์ม การจัดการเหตุการณ์เหล่านี้ทำให้แอปพลิเคชันของเรามีชีวิตชีวา

### Event พื้นฐาน

| Event          | ความหมาย      | ตัวอย่าง                            |
| -------------- | ------------- | ----------------------------------- |
| `onClick`      | คลิก          | `<button onClick={handleClick}>`    |
| `onChange`     | ข้อมูลเปลี่ยน | `<input onChange={handleChange} />` |
| `onSubmit`     | ส่ง Form      | `<form onSubmit={handleSubmit}>`    |
| `onFocus`      | โฟกัส         | `<input onFocus={handleFocus} />`   |
| `onBlur`       | โฟกัสออก      | `<input onBlur={handleBlur} />`     |
| `onKeyPress`   | กดแป้น        | `<input onKeyPress={handleKey} />`  |
| `onMouseEnter` | เลื่อนเข้า    | `<div onMouseEnter={handle}>`       |
| `onMouseLeave` | เลื่อนออก     | `<div onMouseLeave={handle}>`       |

### ตัวอย่าง 1: Simple Click

```javascript
export default function SimpleClick() {
  function handleClick() {
    alert("ปุ่มถูกคลิกแล้ว");
  }

  return (
    <button
      onClick={handleClick}
      style={{
        padding: "10px 20px",
        fontSize: "16px",
        backgroundColor: "#007bff",
        color: "white",
        border: "none",
        borderRadius: "4px",
        cursor: "pointer",
      }}
    >
      คลิกฉัน
    </button>
  );
}
```

### ตัวอย่าง 2: Input Text

```javascript
import { useState } from "react";

export default function InputExample() {
  const [text, setText] = useState("");

  function handleChange(event) {
    setText(event.target.value);
  }

  return (
    <div>
      <input
        type="text"
        value={text}
        onChange={handleChange}
        placeholder="พิมพ์อะไรสักอย่าง"
        style={{ padding: "8px", fontSize: "16px" }}
      />
      <p>
        คุณพิมพ์: <strong>{text}</strong>
      </p>
    </div>
  );
}
```

### ตัวอย่าง 3: Form Submit

```javascript
import { useState } from "react";

export default function LoginForm() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  function handleSubmit(event) {
    event.preventDefault(); // ป้องกันการ reload
    console.log("Username:", username);
    console.log("Password:", password);
    alert(`เข้าสู่ระบบเป็น ${username}`);

    // รีเซ็ต
    setUsername("");
    setPassword("");
  }

  return (
    <form
      onSubmit={handleSubmit}
      style={{
        maxWidth: "300px",
        margin: "20px auto",
        border: "1px solid #ddd",
        padding: "20px",
        borderRadius: "8px",
      }}
    >
      <h2>เข้าสู่ระบบ</h2>

      <div style={{ marginBottom: "15px" }}>
        <label>ชื่อผู้ใช้</label>
        <input
          type="text"
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          placeholder="สมชาย"
          style={{ width: "100%", padding: "8px", marginTop: "5px" }}
        />
      </div>

      <div style={{ marginBottom: "15px" }}>
        <label>รหัสผ่าน</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="••••••"
          style={{ width: "100%", padding: "8px", marginTop: "5px" }}
        />
      </div>

      <button
        type="submit"
        style={{
          width: "100%",
          padding: "10px",
          backgroundColor: "#28a745",
          color: "white",
          border: "none",
          borderRadius: "4px",
          cursor: "pointer",
        }}
      >
        เข้าสู่ระบบ
      </button>
    </form>
  );
}
```

---

## Form Inputs - Controlled Components

บทนี้จะศึกษาวิธีสร้างฟอร์มที่ทำงานร่วมกับ State ทำให้เราควบคุมค่าของ Input ได้ทั้งหมด และสามารถอ่านค่าที่ผู้ใช้พิมพ์เข้ามาในเวลาจริง

### Controlled Components

**Controlled Component** คือ Input ที่ค่าของมันถูกควบคุมโดย State

### ตัวอย่าง

```javascript
import { useState } from "react";

export default function UserForm() {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
    message: "",
    subscribe: false,
  });

  // ฟังก์ชนจัดการคอมพิวเตอร์
  function handleChange(event) {
    const { name, value, type, checked } = event.target;

    setFormData((prev) => ({
      ...prev,
      [name]: type === "checkbox" ? checked : value,
    }));
  }

  function handleSubmit(event) {
    event.preventDefault();
    console.log("ข้อมูลที่ส่ง:", formData);
  }

  return (
    <form
      onSubmit={handleSubmit}
      style={{
        maxWidth: "500px",
        margin: "20px auto",
        padding: "20px",
        border: "1px solid #ddd",
        borderRadius: "8px",
      }}
    >
      <h2>ฟอร์มติดต่อ</h2>

      {/* Text Input */}
      <div style={{ marginBottom: "15px" }}>
        <label>ชื่อ:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleChange}
          placeholder="กรอกชื่อ"
          style={{ width: "100%", padding: "8px", marginTop: "5px" }}
        />
      </div>

      {/* Email Input */}
      <div style={{ marginBottom: "15px" }}>
        <label>อีเมล:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
          placeholder="example@mail.com"
          style={{ width: "100%", padding: "8px", marginTop: "5px" }}
        />
      </div>

      {/* Textarea */}
      <div style={{ marginBottom: "15px" }}>
        <label>ข้อความ:</label>
        <textarea
          name="message"
          value={formData.message}
          onChange={handleChange}
          placeholder="พิมพ์ข้อความ"
          style={{
            width: "100%",
            padding: "8px",
            marginTop: "5px",
            minHeight: "100px",
          }}
        />
      </div>

      {/* Checkbox */}
      <div style={{ marginBottom: "15px" }}>
        <input
          type="checkbox"
          name="subscribe"
          checked={formData.subscribe}
          onChange={handleChange}
        />
        <label style={{ marginLeft: "8px" }}>ต้องการรับข้อมูลข่าวสาร</label>
      </div>

      <button
        type="submit"
        style={{
          padding: "10px 20px",
          backgroundColor: "#007bff",
          color: "white",
          border: "none",
          borderRadius: "4px",
          cursor: "pointer",
        }}
      >
        ส่งข้อมูล
      </button>

      {/* Display Data */}
      <div
        style={{
          marginTop: "20px",
          padding: "15px",
          backgroundColor: "#f0f0f0",
          borderRadius: "4px",
        }}
      >
        <h3>📋 ข้อมูลที่กรอก:</h3>
        <p>
          <strong>ชื่อ:</strong> {formData.name || "ยังไม่กรอก"}
        </p>
        <p>
          <strong>อีเมล:</strong> {formData.email || "ยังไม่กรอก"}
        </p>
        <p>
          <strong>ข้อความ:</strong> {formData.message || "ยังไม่กรอก"}
        </p>
        <p>
          <strong>สมัครรับข่าร:</strong> {formData.subscribe ? "ใช่" : "ไม่ใช่"}
        </p>
      </div>
    </form>
  );
}
```

---

## Conditional Rendering - แสดงผลตามเงื่อนไข

บทนี้เราจะเรียนรู้วิธีแสดงหรือซ่อน Component ตามเงื่อนไข เช่น แสดงปุ่มเข้าสู่ระบบเมื่อยังไม่เข้า หรือแสดงสิ่งที่ต่างกันตามสถานะการโหลดข้อมูล

### ตัวอย่าง 1: Ternary Operator

```javascript
import { useState } from "react";

export default function Login() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  return (
    <div style={{ padding: "20px" }}>
      {isLoggedIn ? (
        <div>
          <h1>ยินดีต้อนรับ (กำลังเข้าสู่ระบบ)</h1>
          <button onClick={() => setIsLoggedIn(false)}>ออกจากระบบ</button>
        </div>
      ) : (
        <div>
          <h1>กรุณาเข้าสู่ระบบ</h1>
          <button onClick={() => setIsLoggedIn(true)}>เข้าสู่ระบบ</button>
        </div>
      )}
    </div>
  );
}
```

### ตัวอย่าง 2: Logical AND (&&)

```javascript
import { useState } from "react";

export default function Notification() {
  const [hasMessage, setHasMessage] = useState(false);

  return (
    <div>
      {hasMessage && (
        <div
          style={{
            backgroundColor: "#d4edda",
            border: "1px solid #c3e6cb",
            padding: "15px",
            borderRadius: "4px",
            marginBottom: "20px",
          }}
        >
          คุณมีข้อความใหม่
        </div>
      )}

      <button onClick={() => setHasMessage(!hasMessage)}>
        {hasMessage ? "ลบการแจ้งเตือน" : "เพิ่มการแจ้งเตือน"}
      </button>
    </div>
  );
}
```

### ตัวอย่าง 3: Status Display

```javascript
import { useState } from "react";

export default function StatusChecker() {
  const [status, setStatus] = useState("idle"); // idle, loading, success, error

  function handleClick() {
    setStatus("loading");
    setTimeout(() => {
      setStatus(Math.random() > 0.5 ? "success" : "error");
    }, 2000);
  }

  return (
    <div style={{ padding: "20px" }}>
      <button onClick={handleClick}>ตรวจสอบสถานะ</button>

      <div style={{ marginTop: "20px" }}>
        {status === "idle" && <p>กดปุ่มเพื่อตรวจสอบ</p>}

        {status === "loading" && (
          <p style={{ color: "#ffc107" }}>กำลังตรวจสอบ...</p>
        )}

        {status === "success" && <p style={{ color: "#28a745" }}>สำเร็จแล้ว</p>}

        {status === "error" && (
          <p style={{ color: "#dc3545" }}>เกิดข้อผิดพลาด</p>
        )}
      </div>
    </div>
  );
}
```

---

## ตัวอย่าง Todo App

สร้าง **Todo App** ที่สามารถเพิ่ม/ลบรายการได้

### ตัวอย่าง: Todo App

```javascript
import { useState } from "react";

export default function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");

  function addTodo() {
    if (input.trim()) {
      setTodos([...todos, { id: Date.now(), text: input }]);
      setInput("");
    }
  }

  function deleteTodo(id) {
    setTodos(todos.filter((todo) => todo.id !== id));
  }

  return (
    <div
      style={{
        maxWidth: "500px",
        margin: "20px auto",
        padding: "20px",
        border: "1px solid #ddd",
        borderRadius: "8px",
      }}
    >
      <h1>รายการที่ต้องทำ</h1>

      {/* Input */}
      <div style={{ marginBottom: "15px", display: "flex", gap: "10px" }}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === "Enter" && addTodo()}
          placeholder="เพิ่มสิ่งที่ต้องทำ..."
          style={{
            flex: 1,
            padding: "10px",
            fontSize: "16px",
            borderRadius: "4px",
            border: "1px solid #ddd",
          }}
        />
        <button
          onClick={addTodo}
          style={{
            padding: "10px 20px",
            backgroundColor: "#28a745",
            color: "white",
            border: "none",
            borderRadius: "4px",
            cursor: "pointer",
          }}
        >
          เพิ่ม
        </button>
      </div>

      {/* List */}
      <ul style={{ listStyle: "none", padding: 0 }}>
        {todos.map((todo) => (
          <li
            key={todo.id}
            style={{
              backgroundColor: "#f9f9f9",
              padding: "12px",
              marginBottom: "8px",
              borderRadius: "4px",
              display: "flex",
              justifyContent: "space-between",
              alignItems: "center",
              border: "1px solid #ddd",
            }}
          >
            <span>{todo.text}</span>
            <button
              onClick={() => deleteTodo(todo.id)}
              style={{
                padding: "5px 10px",
                backgroundColor: "#dc3545",
                color: "white",
                border: "none",
                borderRadius: "4px",
                cursor: "pointer",
              }}
            >
              ลบ
            </button>
          </li>
        ))}
      </ul>

      {todos.length === 0 && (
        <p style={{ textAlign: "center", color: "#999" }}>
          ยังไม่มีรายการ เพิ่มเลย
        </p>
      )}
    </div>
  );
}
```

---

## สรุปสัปดาห์ที่ 12

| หัวข้อ               | สิ่งที่เรียนรู้                     |
| -------------------- | ----------------------------------- |
| **useState**         | จัดการข้อมูลที่เปลี่ยนแปลงได้       |
| **Event**            | ตอบสนองต่อเหตุการณ์ (click, change) |
| **Controlled Input** | Input ที่ค่าถูกควบคุมโดย State      |
| **Conditional**      | แสดงผลตามสภาวะ (if/else)            |

---

## สัปดาห์หน้า

ต่อไปเราจะเรียนรู้:

- **useEffect Hook** - Side effects
- **Fetching Data** - เรียก API
- **Loading + Error** - สถานะการดึงข้อมูล
- **Dependency Array** - ตรวจสอบการเปลี่ยนแปลง
