🇰🇭 ជាភាសាខ្មែរ · Complete React Course

រៀន React
ពីចាប់ផ្តើម ដល់ Expert

មេរៀន React ពេញលេញជាភាសាខ្មែរ — JSX, Components, Hooks, Context, Router និងច្រើនទៀត ជាមួយឧទាហរណ៍ជាក់ស្តែង

15+
មេរៀន
50+
ឧទាហរណ៍
3
កម្រិត
1

ការណែនាំអំពី React

ចាប់ផ្តើម

React គឺជា JavaScript Library ដែលបង្កើតឡើងដោយ Meta (Facebook) ក្នុងឆ្នាំ 2013 សម្រាប់បង្កើត User Interface (UI) ។ React ជួយឱ្យយើងបង្កើត Web Application ដែលឆ្លើយតបលឿន និងអាចប្រើប្រាស់ Code ម្តងហើយប្រើម្តងទៀតបាន។

Virtual DOM

React ប្រើ Virtual DOM ធ្វើឱ្យ UI Update លឿនជាងធម្មតា

🧩

Component-Based

Code ត្រូវបែងចែកជា Components តូចៗ ងាយស្រួលគ្រប់គ្រង

🔄

One-Way Data Flow

ទិន្នន័យហូរពី Parent ទៅ Child តែមួយទិស

🌍

Ecosystem ធំ

មាន Library ជំនួយច្រើន: Router, Redux, Next.js ។ល។

💡 ដឹងទេ? React ត្រូវបានប្រើដោយ Facebook, Instagram, Netflix, Airbnb, Uber និងក្រុមហ៊ុនធំៗជាច្រើនទៀត!
2

ការដំឡើង React Project

ចាប់ផ្តើម

យើងប្រើ ViteCreate React App ដើម្បីចាប់ផ្តើម Project ថ្មី។ Vite គឺលឿនជាង CRA ហើយជាជម្រើសដែលពេញនិយមបច្ចុប្បន្ន។

ប្រើ Vite (ណែនាំ)

Terminal
# បង្កើត Project ថ្មី
npm create vite@latest my-app -- --template react

# ចូលទៅក្នុង Folder
cd my-app

# ដំឡើង Dependencies
npm install

# រត់ Development Server
npm run dev

រចនាសម្ព័ន្ធ Folder

Project Structure
my-app/
├── node_modules/
├── public/
│   └── vite.svg
├── src/
│   ├── App.jsx       ← Component ចម្បង
│   ├── App.css
│   └── main.jsx     ← Entry point
├── index.html
└── package.json
3

JSX — JavaScript + HTML

ចាប់ផ្តើម

JSX (JavaScript XML) គឺជា Syntax Extension ដែលអនុញ្ញាតឱ្យយើងសរសេរ HTML ក្នុង JavaScript ។ JSX ត្រូវបាន Compile ទៅជា JavaScript ធម្មតា។

JSX.jsx
// ឧទាហរណ៍ JSX ជាមូលដ្ឋាន
const element = (
  <div className="container">
    <h1>សួស្ដី React!</h1>
    <p>ខ្ញុំរៀន JSX</p>
  </div>
);

// ប្រើ Expression ក្នុង JSX ដោយ { }
const name = "សុភា";
const age = 20;

const greeting = (
  <p>
    ឈ្មោះ: {name}, អាយុ: {age} ឆ្នាំ
  </p>
);

// Conditional Rendering ដោយ ternary
const isLoggedIn = true;
const ui = (
  <div>
    {isLoggedIn ? <p>ស្វាគមន៍</p> : <p>សូម Login</p>}
  </div>
);
⚠️ ចំណុចសំខាន់ ក្នុង JSX ត្រូវប្រើ className ជំនួស class, htmlFor ជំនួស for

JSX Rules

HTMLJSXពន្យល់
class="..."className="..."class គឺ reserved word ក្នុង JS
for="..."htmlFor="..."for ក៏ reserved word ដែរ
<br><br />Self-closing tag ត្រូវ Close
2 elementswrap ក្នុង <></>JSX Return element តែ 1
4

Components

ចាប់ផ្តើម

Component គឺជា Building Block នៃ React Application ។ Component ដូចជា Function ដែល Return JSX ។ ឈ្មោះ Component ត្រូវចាប់ផ្តើមដោយ Capital Letter ។

WelcomeCard.jsx
// Functional Component ជាមូលដ្ឋាន
function WelcomeCard() {
  return (
    <div style={{ padding: '20px', background: '#f0f0f0' }}>
      <h2>🇰🇭 សួស្ដីអ្នករៀន React!</h2>
      <p>ចូលរួមរៀន React ជាភាសាខ្មែរ</p>
    </div>
  );
}

// Component Nesting — ប្រើ Component ក្នុង Component
function Header() {
  return <h1>🚀 Website ខ្ញុំ</h1>;
}

function App() {
  return (
    <div>
      <Header />         ← ប្រើ Component
      <WelcomeCard />    ← ប្រើ Component
      <WelcomeCard />    ← ប្រើបានម្ដងទៀត!
    </div>
  );
}

export default App;
✅ ល្អ Component ម្តង 1 ឯកសារ (.jsx) — ឧ. Button.jsx, Card.jsx, Navbar.jsx ។ ងាយស្រួលស្វែងរក និងថែទាំ!
5

Props — ការបញ្ជូនទិន្នន័យ

ចាប់ផ្តើម

Props (Properties) ជាវិធីបញ្ជូនទិន្នន័យពី Parent Component ទៅ Child Component ។ Props អានបានតែ (Read-Only) — Child មិនអាចផ្លាស់ប្ដូរ Props បាន។

StudentCard.jsx
// Child Component ទទួល Props
function StudentCard({ name, age, score }) {
  return (
    <div style={{ border: '1px solid #ccc', padding: 16, margin: 8 }}>
      <h3>👤 {name}</h3>
      <p>អាយុ: {age} ឆ្នាំ</p>
      <p>ពិន្ទុ: {score} / 100</p>
    </div>
  );
}

// Parent Component ផ្ញើ Props
function App() {
  return (
    <div>
      <StudentCard
        name="សុភា"
        age={20}
        score={95}
      />
      <StudentCard
        name="ដារ៉ា"
        age={22}
        score={88}
      />
    </div>
  );
}

Default Props

DefaultProps.jsx
// Props Default Value
function Button({ text = "ចុច", color = "blue", onClick }) {
  return (
    <button
      style={{ background: color, color: '#fff', padding: '8px 16px' }}
      onClick={onClick}
    >
      {text}
    </button>
  );
}

// ការប្រើប្រាស់
<Button />                          → "ចុច" blue
<Button text="Save" color="green" />  → "Save" green
6

State & useState Hook

មធ្យម

State គឺជាទិន្នន័យ Dynamic ក្នុង Component ។ នៅពេល State ផ្លាស់ប្ដូរ React នឹង Re-render Component ដោយស្វ័យប្រវត្តិ។ យើងប្រើ useState Hook ដើម្បីប្រកាស State ។

Counter.jsx
import { useState } from 'react';

function Counter() {
  // [value, setter] = useState(initialValue)
  const [count, setCount] = useState(0);

  return (
    <div>
      <h2>ចំនួន: {count}</h2>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

State ជា Object

UserForm.jsx
function UserForm() {
  const [user, setUser] = useState({
    name: '',
    email: ''
  });

  const handleChange = (e) => {
    // Spread operator — copy state ចាស់ ហើយ update field ថ្មី
    setUser({ ...user, [e.target.name]: e.target.value });
  };

  return (
    <div>
      <input name="name" value={user.name} onChange={handleChange} />
      <input name="email" value={user.email} onChange={handleChange} />
      <p>ឈ្មោះ: {user.name}</p>
    </div>
  );
}
❌ កុច្ចបិទ! កុំផ្លាស់ប្ដូរ State ដោយផ្ទាល់ ។ count = count + 1 ❌ ។ ត្រូវប្រើ Setter: setCount(count + 1)
7

Event Handling

មធ្យម

React ប្រើ Synthetic Events ដែលមានលក្ខណៈដូច DOM Events ធម្មតា ប៉ុន្តែ Consistent ក្នុងគ្រប់ Browser ។

Events.jsx
function EventDemo() {
  const [msg, setMsg] = useState('');

  // onClick
  const handleClick = () => setMsg("ចុចហើយ!");

  // onChange
  const handleChange = (e) => setMsg(e.target.value);

  // onSubmit
  const handleSubmit = (e) => {
    e.preventDefault();  // បញ្ឈប់ Page Reload
    alert(`Submit: ${msg}`);
  };

  // onMouseEnter / onMouseLeave
  const [hovered, setHovered] = useState(false);

  return (
    <div>
      <button onClick={handleClick}>ចុចខ្ញុំ</button>
      <input onChange={handleChange} placeholder="វាយអ្វីមួយ..." />
      <p
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
        style={{ color: hovered ? 'red' : 'black' }}
      >
        Hover ខ្ញុំ!
      </p>
    </div>
  );
}
8

useEffect Hook

មធ្យម

useEffect ជួយឱ្យ Component ធ្វើ Side Effects — ដូចជា API Call, Timer, Event Listener ។ useEffect រត់ក្រោយ Render ។

useEffect.jsx
import { useState, useEffect } from 'react';

function DataFetcher() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);

  // [] = រត់ម្ដងតែ Component Mount
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res => res.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      });
  }, []); ← Dependency Array

  if (loading) return <p>⏳ កំពុងផ្ទុក...</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

// useEffect ជាមួយ Dependency
function SearchComponent() {
  const [query, setQuery] = useState('');

  // រត់រាល់ពេល query ផ្លាស់ប្ដូរ
  useEffect(() => {
    console.log(`ស្វែងរក: ${query}`);
  }, [query]); ← run when query changes

  return <input value={query} onChange={e => setQuery(e.target.value)} />;
}
Dependency Arrayពេលណា useEffect រត់
គ្មាន []រត់រាល់ Render
[] ទទេរត់ម្ដង (Mount)
[value]រត់ពេល value ផ្លាស់ប្ដូរ
9

Lists & Keys

មធ្យម

ដើម្បី Render List of Items ក្នុង React យើងប្រើ .map() ។ Props key ជួយ React កំណត់ Item ណាផ្លាស់ប្ដូរ — ត្រូវ Unique ក្នុង List ។

TodoList.jsx
function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: 'រៀន JSX', done: true },
    { id: 2, text: 'ស្គាល់ Components', done: true },
    { id: 3, text: 'Master Hooks', done: false },
  ]);

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id
        ? { ...todo, done: !todo.done }
        : todo
    ));
  };

  return (
    <ul>
      {todos.map(todo => (
        <li
          key={todo.id}
          onClick={() => toggleTodo(todo.id)}
          style={{
            textDecoration: todo.done ? 'line-through' : 'none',
            cursor: 'pointer'
          }}
        >
          {todo.done ? '✅' : '⬜'} {todo.text}
        </li>
      ))}
    </ul>
  );
}
10

Controlled Forms

មធ្យម

ក្នុង React Form Input ត្រូវ Control ដោយ State (Controlled Component) ។ ន​ ​ value ត្រូវ bind ជាមួយ State ហើយ onChange update State ។

RegisterForm.jsx
function RegisterForm() {
  const [form, setForm] = useState({
    name: '', email: '', password: '', role: 'student'
  });
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    setForm({ ...form, [e.target.name]: e.target.value });
  };

  const validate = () => {
    const err = {};
    if (!form.name) err.name = 'ត្រូវវាយឈ្មោះ';
    if (!form.email.includes('@')) err.email = 'Email មិនត្រឹមត្រូវ';
    return err;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    const err = validate();
    if (Object.keys(err).length > 0) {
      setErrors(err);
    } else {
      alert(`ចុះឈ្មោះ: ${form.name}`);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" value={form.name} onChange={handleChange} />
      {errors.name && <span style={{color:'red'}}>{errors.name}</span>}

      <select name="role" value={form.role} onChange={handleChange}>
        <option value="student">សិស្ស</option>
        <option value="teacher">គ្រូ</option>
      </select>

      <button type="submit">ចុះឈ្មោះ</button>
    </form>
  );
}
11

Context API

ខ្ពស់

Context API ដោះស្រាយបញ្ហា Prop Drilling — ការបញ្ជូន Props ច្រើនថ្នាក់។ Context អាចចែករំលែកទិន្នន័យដើម្បីប្រើក្នុង Component ទូទាំង App ។

🎯 ប្រើ Context នៅពេល Theme (Dark/Light), Language (i18n), User Auth, Shopping Cart — ទិន្នន័យ Global ។
ThemeContext.jsx
import { createContext, useContext, useState } from 'react';

// 1. បង្កើត Context
const ThemeContext = createContext();

// 2. Provider — wrap Component ដែលចង់ប្រើ
function ThemeProvider({ children }) {
  const [dark, setDark] = useState(false);

  return (
    <ThemeContext.Provider value={{ dark, setDark }}>
      {children}
    </ThemeContext.Provider>
  );
}

// 3. Custom Hook ងាយស្រួលប្រើ
const useTheme = () => useContext(ThemeContext);

// 4. ប្រើ Context ក្នុង Component ណាក៏បាន
function Navbar() {
  const { dark, setDark } = useTheme();

  return (
    <nav style={{ background: dark ? '#333' : '#fff' }}>
      <button onClick={() => setDark(!dark)}>
        {dark ? '☀️ Light' : '🌙 Dark'}
      </button>
    </nav>
  );
}

// App.jsx
function App() {
  return (
    <ThemeProvider>
      <Navbar />
      <MainContent />
    </ThemeProvider>
  );
}
12

Custom Hooks

ខ្ពស់

Custom Hook គឺ Function ដែល Extract Logic ចេញពី Component ។ ជួយ Reuse Logic ដូចជា API Fetching, Form Handling, Local Storage ។ ឈ្មោះ Custom Hook ចាប់ផ្តើមដោយ use

useFetch.js
// Custom Hook: useFetch
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);
    fetch(url)
      .then(res => {
        if (!res.ok) throw new Error('Fetch failed');
        return res.json();
      })
      .then(d => setData(d))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, [url]);

  return { data, loading, error };
}

// ប្រើ useFetch ក្នុង Component
function UserList() {
  const { data, loading, error } =
    useFetch('https://jsonplaceholder.typicode.com/users');

  if (loading) return <p>⏳ កំពុងផ្ទុក...</p>;
  if (error)   return <p>❌ Error: {error}</p>;

  return <ul>{data.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

useLocalStorage Hook

useLocalStorage.js
function useLocalStorage(key, initial) {
  const [value, setValue] = useState(() => {
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initial;
    } catch { return initial; }
  });

  const set = (v) => {
    setValue(v);
    localStorage.setItem(key, JSON.stringify(v));
  };

  return [value, set];
}
13

useReducer

ខ្ពស់

useReducer ល្អជាង useState ពេល State មានភាពស្មុគស្មាញ ឬ Logic ប្រើ Action ច្រើនប្រភេទ (ដូច Redux) ។

ShoppingCart.jsx
import { useReducer } from 'react';

// Reducer Function
function cartReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return { ...state, items: [...state.items, action.item] };

    case 'REMOVE':
      return {
        ...state,
        items: state.items.filter(i => i.id !== action.id)
      };

    case 'CLEAR':
      return { items: [] };

    default:
      return state;
  }
}

function Cart() {
  const [state, dispatch] = useReducer(cartReducer, { items: [] });

  return (
    <div>
      <button onClick={() => dispatch({
        type: 'ADD',
        item: { id: Date.now(), name: 'ទំនិញ' }
      })}>➕ បន្ថែម</button>

      <button onClick={() => dispatch({ type: 'CLEAR' })}>🗑️ Clear</button>

      <p>ចំនួន: {state.items.length}</p>
    </div>
  );
}
14

useMemo & useCallback

ខ្ពស់

Hooks ទាំងពីរនេះជួយ Optimize Performance ដោយ Memoize (Cache) Result ។

Optimization.jsx
import { useMemo, useCallback, memo } from 'react';

// useMemo — Cache ការគណនាស្មុគ
function ProductList({ products, filter }) {
  const filtered = useMemo(() => {
    // Operation ស្មុគ — គណនាតែពេល products/filter ផ្លាស់ប្ដូរ
    return products
      .filter(p => p.price > filter.minPrice)
      .sort((a, b) => a.price - b.price);
  }, [products, filter]);

  return <ul>{filtered.map(p => <li key={p.id}>{p.name}</li>)}</ul>;
}

// useCallback — Cache Function Reference
function Parent() {
  const [count, setCount] = useState(0);

  // Function នេះ មិន Re-create ពេល count re-render
  const handleDelete = useCallback((id) => {
    console.log('delete', id);
  }, []); ← no dependencies = never recreate

  return <ChildComponent onDelete={handleDelete} />;
}

// memo — Re-render Component ត្រឹមតែ Props ផ្លាស់ប្ដូរ
const ChildComponent = memo(({ onDelete }) => {
  return <button onClick={() => onDelete(1)}>លុប</button>;
});
Hook / APICache អ្វីប្រើពេល
useMemoComputed ValueCalculation ស្មុគ
useCallbackFunctionPass function ទៅ Child
React.memoComponentComponent Re-render ញឹកពេក
15

React Router v6

ខ្ពស់

React Router គ្រប់គ្រង Navigation ក្នុង Single Page Application (SPA) ។ ប្រើ URL ដើម្បីបង្ហាញ Component ផ្សេងៗ ដោយ Reload Page

App.jsx (with Router)
import { BrowserRouter, Routes, Route, Link, useParams, useNavigate }
  from 'react-router-dom';

// Pages
const Home = () => <h1>🏠 ទំព័រដើម</h1>;
const About = () => <h1>ℹ️ អំពីយើង</h1>;
const NotFound = () => <h1>404 — រកមិនឃើញ</h1>;

// Dynamic Route
function UserDetail() {
  const { id } = useParams();
  return <h2>អ្នកប្រើប្រាស់ #{id}</h2>;
}

// Navigation Programmatic
function LoginPage() {
  const navigate = useNavigate();

  const handleLogin = () => {
    // ក្រោយ Login ជោគជ័យ → redirect
    navigate('/dashboard');
  };

  return <button onClick={handleLogin}>Login</button>;
}

// Main App
function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">ដើម</Link> |
        <Link to="/about">អំពី</Link> |
        <Link to="/user/5">User #5</Link>
      </nav>

      <Routes>
        <Route path="/"         element={<Home />} />
        <Route path="/about"    element={<About />} />
        <Route path="/user/:id" element={<UserDetail />} />
        <Route path="*"         element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}
🗺️ ដំឡើង React Router npm install react-router-dom

🗺️ React Learning Roadmap

🌱

ចំណុចចាប់ផ្តើម

JSX → Components → Props → Event → State (useState)

🔥

កម្រិតមធ្យម

useEffect → Lists → Forms → API Fetch → Lifecycle

🚀

កម្រិតខ្ពស់

Context → Custom Hooks → useReducer → Router → Performance

Expert

Next.js → TypeScript → Testing → Redux Toolkit → Deployment