❖ 1. ស្គាល់ដំបូងអំពី React

1.1 React គឺជាអ្វី រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

React ជា Library JavaScript (មិនមែន Framework ពេញលេញដូច Angular) បង្កើតដោយ Facebook សម្រាប់ស្ថាបនាចំណុចប្រទាក់អ្នកប្រើប្រាស់ (UI) ដោយបំបែកជា "Component" តូចៗ ដែលអាចប្រើឡើងវិញបាន ជំនួសឲ្យសរសេរ DOM Manipulation ដោយផ្ទាល់ដៃដូច JavaScript ធម្មតា។

ហេតុអ្វីត្រូវប្រើ React? ពេល Application ធំឡើង ការគ្រប់គ្រង DOM ដោយផ្ទាល់ (querySelector, addEventListener ជាច្រើន) ក្លាយជាស្មុគស្មាញ និងពិបាកតាមដាន។ React ជួយឲ្យកូដមានរបៀប ដោយផ្តោតលើ "UI = f(State)"។

1.2 ការដំឡើង React រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

វិធីការប្រើប្រាស់
Vite (ណែនាំ)npm create vite@latest my-app -- --template react
Create React Appnpx create-react-app my-app (ចាស់ជាង, យឺតជាង Vite)
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev

1.3 រចនាសម្ព័ន្ធ Project មូលដ្ឋាន រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

File/Folderតួនាទី
src/main.jsxចំណុចចាប់ផ្ដើម៖ "Mount" Component ចម្បងចូល HTML
src/App.jsxComponent ចម្បងរបស់ Application
index.htmlឯកសារ HTML តែមួយគត់ (Single Page Application)

❖ 2. JSX ជាមូលដ្ឋាន

2.1 JSX គឺជាអ្វី រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

JSX (JavaScript XML) អនុញ្ញាតឲ្យសរសេរ HTML ដោយផ្ទាល់ចូលក្នុងកូដ JavaScript មិនមែនជា HTML ពិតទេ គឺជា Syntax ពិសេសដែល React បម្លែងទៅជា JavaScript object ជាបន្តបន្ទាប់។

const element = <h1>សួស្តី React!</h1>;
ចំណាំ៖ JSX ត្រូវតែមាន Element តែមួយនៅកម្រិតដំបូង (Wrap ដោយ <div><></> Fragment បើមានច្រើនជាមួយគ្នា)។

2.2 ការបញ្ចូល JavaScript ចូល JSX រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ប្រើវង់ក្រចកមូល { } ដើម្បីបញ្ចូលកន្សោម (expression) JavaScript ណាមួយចូលក្នុង JSX។

function Welcome() {
  const name = "សុភា";
  return <h1>សួស្តី {name}!</h1>;
}

2.3 ភាពខុសគ្នារវាង JSX Attribute និង HTML Attribute រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

HTMLJSXហេតុអ្វី
classclassNameclass ជា Keyword រក្សាទុកក្នុង JavaScript
forhtmlForfor ក៏ជា Keyword រក្សាទុកដែរ
onclickonClickJSX ប្រើ camelCase សម្រាប់ Event ទាំងអស់

❖ 3. Components & Props

3.1 Function Component រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Component ជា Function JavaScript ធម្មតាមួយ ដែលត្រឡប់ JSX ជាឯកតាមូលដ្ឋានបំផុតរបស់ React Application ណាមួយ។

function Greeting() {
  return <h2>សូមស្វាគមន៍!</h2>;
}

// ប្រើ Component នេះក្នុង Component ផ្សេងទៀត
function App() {
  return (
    <div>
      <Greeting />
    </div>
  );
}
សំខាន់! ឈ្មោះ Component ត្រូវតែចាប់ផ្ដើមដោយអក្សរធំ (ឧ. Greeting មិនមែន greeting) បើមិនដូច្នេះទេ React នឹងចាត់ទុកវាជា HTML Tag ធម្មតា មិនមែន Component។

3.2 Props (ការផ្ញើទិន្នន័យទៅ Component) រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Props (Properties) ជាទិន្នន័យដែលបញ្ជូនពី Component មេ ទៅ Component កូន ដូចជា Parameter របស់ Function ដែរ តែសម្រាប់ JSX។

function Greeting(props) {
  return <h2>សួស្តី {props.name}!</h2>;
}

function App() {
  return (
    <div>
      <Greeting name="សុខា" />
      <Greeting name="ដារា" />
    </div>
  );
}
គន្លឹះ៖ Props ជា Read-only។ Component កូនមិនអាចកែប្រែ Props ដែលទទួលបានដោយផ្ទាល់ទេ (លំហូរទិន្នន័យតែមួយទិស ពី​លើចុះក្រោម)។

❖ 4. State ជាមួយ useState

4.1 State គឺជាអ្វី ខុសពី Props ត្រង់ណា រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

State ជាទិន្នន័យខាងក្នុងរបស់ Component ខ្លួនឯង ដែលអាចផ្លាស់ប្តូរតាមពេលវេលា (ខុសពី Props ដែលមកពីខាងក្រៅ និងជា Read-only)។ ពេល State ផ្លាស់ប្តូរ React នឹង Render Component នោះឡើងវិញដោយស្វ័យប្រវត្តិ។

4.2 useState Hook រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>ចំនួន: {count}</p>
      <button onClick={() => setCount(count + 1)}>បូក</button>
    </div>
  );
}
ផ្នែកន័យ
countតម្លៃបច្ចុប្បន្នរបស់ State
setCountFunction សម្រាប់កំណត់តម្លៃ State ថ្មី
useState(0)តម្លៃដំបូង (Initial Value) របស់ State
សំខាន់! កុំកែប្រែ State ដោយផ្ទាល់ (ឧ. count = count + 1) ត្រូវហៅ setCount() ជានិច្ច ដើម្បីឲ្យ React ដឹងថាត្រូវ Render ឡើងវិញ។

❖ 5. Event Handling ក្នុង React

5.1 ការគ្រប់គ្រង Event រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

function Button() {
  function handleClick() {
    console.log("ចុចរួចហើយ!");
  }

  return <button onClick={handleClick}>ចុចខ្ញុំ</button>;
}
ចំណាំ៖ សរសេរ onClick={handleClick} មិនមែន onClick={handleClick()} ទេ ដាក់វង់ក្រចកនឹងហៅ Function ភ្លាមពេល Render ជំនួសឲ្យរង់ចាំចុច។

5.2 ការទទួល Input ពីអ្នកប្រើប្រាស់ រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

function NameInput() {
  const [name, setName] = useState("");

  return (
    <input
      value={name}
      onChange={(e) => setName(e.target.value)}
    />
  );
}

❖ 6. Conditional Rendering & Lists

6.1 Conditional Rendering រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

ក្នុង JSX អាចប្រើ Ternary Operator ឬ && ដើម្បីបង្ហាញខ្លឹមសារខុសគ្នាទៅតាមលក្ខខណ្ឌ។

function Status({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? <p>សូមស្វាគមន៍មកវិញ!</p> : <p>សូមចូល Login</p>}
      {isLoggedIn && <button>ចាកចេញ</button>}
    </div>
  );
}

6.2 ការបង្ហាញបញ្ជីជាមួយ .map() រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

function FruitList() {
  const fruits = ["ស្វាយ", "ចេក", "ឪឡឹក"];

  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}
សំខាន់! Attribute key ចាំបាច់ត្រូវដាក់ ពេល Render បញ្ជីតាម .map() ជួយ React កំណត់ថាធាតុមួយណាបានផ្លាស់ប្តូរ ដោយមិនចាំបាច់ Render ធាតុទាំងអស់ឡើងវិញ។ ជាទូទៅគួរប្រើ ID ពិតប្រាកដជំនួស index បើអាចធ្វើបាន។

❖ 7. useEffect & Side Effects

7.1 useEffect គឺជាអ្វី រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Side Effect ជាកិច្ចការណាមួយដែលកើតឡើងក្រៅពី Render ធម្មតា (ឧ. ហៅ API, កំណត់ Timer, ភ្ជាប់ Event ទៅ window)៖ useEffect ជា Hook សម្រាប់គ្រប់គ្រងកិច្ចការទាំងនេះ។

import { useState, useEffect } from "react";

function Clock() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const timer = setInterval(() => setTime(new Date()), 1000);
    return () => clearInterval(timer);  // Cleanup ពេល Component ត្រូវលុប
  }, []);

  return <p>ម៉ោងបច្ចុប្បន្ន: {time.toLocaleTimeString()}</p>;
}

7.2 Dependency Array រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Dependency Arrayដំណើរការនៅពេលណា
[]ដំណើរការតែម្ដងគត់ ពេល Component ដំបូង Render
[count]ដំណើរការរាល់ពេល count ផ្លាស់ប្តូរ
(គ្មាន Array)ដំណើរការរាល់ពេល Render (កម្រប្រើ ជៀសវាងបើអាចបាន)

❖ 8. Forms ក្នុង React

8.1 Controlled Components រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

Controlled Component ជា Input ដែលតម្លៃរបស់វាត្រូវបានគ្រប់គ្រងទាំងស្រុងដោយ React State។ React គឺជា "Single Source of Truth" សម្រាប់ទិន្នន័យក្នុង Form។

function LoginForm() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    console.log(email, password);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      <button type="submit">ចូល</button>
    </form>
  );
}
គន្លឹះ៖ ដូចនឹង JavaScript ធម្មតា e.preventDefault() ចាំបាច់ត្រូវហៅ ដើម្បីការពារកុំឲ្យ Browser Reload ទំព័រពេលបញ្ជូន Form។

❖ 9. គម្រោងអនុវត្ត (Todo App)

9.1 ការរៀបចំគម្រោង រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

តោះផ្សំចំណុចដែលបានរៀនទាំងអស់ (useState, Event Handling, .map(), Conditional Rendering) ធ្វើជាកម្មវិធីតូចមួយសម្រាប់គ្រប់គ្រងកិច្ចការត្រូវធ្វើ (Todo List)។

9.2 កូដពេញលេញ រៀបរៀងដោយ: លោក អ៊ុតថា សៀវអុី

import { useState } from "react";

function TodoApp() {
  const [tasks, setTasks] = useState([]);
  const [input, setInput] = useState("");

  function addTask() {
    if (input.trim() === "") return;
    setTasks([...tasks, { id: Date.now(), text: input, done: false }]);
    setInput("");
  }

  function toggleTask(id) {
    setTasks(tasks.map(task =>
      task.id === id ? { ...task, done: !task.done } : task
    ));
  }

  function removeTask(id) {
    setTasks(tasks.filter(task => task.id !== id));
  }

  return (
    <div>
      <h2>បញ្ជីកិច្ចការត្រូវធ្វើ</h2>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="បញ្ចូលកិច្ចការថ្មី..."
      />
      <button onClick={addTask}>បន្ថែម</button>

      <ul>
        {tasks.map(task => (
          <li key={task.id}>
            <span
              style={{ textDecoration: task.done ? "line-through" : "none" }}
              onClick={() => toggleTask(task.id)}
            >
              {task.text}
            </span>
            <button onClick={() => removeTask(task.id)}>លុប</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoApp;

លំហាត់អនុវត្ត

  1. បន្ថែម Counter បង្ហាញ "ចំនួនកិច្ចការនៅសល់" (Task ដែលមិនទាន់ done) ក្នុង Todo App ខាងលើ។
  2. បន្ថែមប៊ូតុង "សម្អាតកិច្ចការដែលធ្វើរួច" ដែលលុប Task ដែល done: true ទាំងអស់ក្នុងម្ដង។
  3. ប្រើ useEffect រក្សាទុកបញ្ជី Task ទៅ localStorage រាល់ពេល Task ផ្លាស់ប្តូរ ដើម្បីកុំឲ្យបាត់ពេល Reload ទំព័រ។
  4. បន្ថែម Filter Button (ទាំងអស់ / កំពុងធ្វើ / ធ្វើរួច) ដើម្បីបង្ហាញ Task តាមស្ថានភាព។