ការណែនាំអំពី 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 Project
ចាប់ផ្តើមយើងប្រើ Vite ឬ Create React App ដើម្បីចាប់ផ្តើម Project ថ្មី។ Vite គឺលឿនជាង CRA ហើយជាជម្រើសដែលពេញនិយមបច្ចុប្បន្ន។
ប្រើ Vite (ណែនាំ)
# បង្កើត Project ថ្មី npm create vite@latest my-app -- --template react # ចូលទៅក្នុង Folder cd my-app # ដំឡើង Dependencies npm install # រត់ Development Server npm run dev
រចនាសម្ព័ន្ធ Folder
my-app/ ├── node_modules/ ├── public/ │ └── vite.svg ├── src/ │ ├── App.jsx ← Component ចម្បង │ ├── App.css │ └── main.jsx ← Entry point ├── index.html └── package.json
JSX — JavaScript + HTML
ចាប់ផ្តើមJSX (JavaScript XML) គឺជា Syntax Extension ដែលអនុញ្ញាតឱ្យយើងសរសេរ HTML ក្នុង JavaScript ។ JSX ត្រូវបាន Compile ទៅជា JavaScript ធម្មតា។
// ឧទាហរណ៍ 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> );
className ជំនួស class, htmlFor ជំនួស for ។
JSX Rules
| HTML | JSX | ពន្យល់ |
|---|---|---|
class="..." | className="..." | class គឺ reserved word ក្នុង JS |
for="..." | htmlFor="..." | for ក៏ reserved word ដែរ |
<br> | <br /> | Self-closing tag ត្រូវ Close |
| 2 elements | wrap ក្នុង <></> | JSX Return element តែ 1 |
Components
ចាប់ផ្តើមComponent គឺជា Building Block នៃ React Application ។ Component ដូចជា Function ដែល Return JSX ។ ឈ្មោះ Component ត្រូវចាប់ផ្តើមដោយ Capital Letter ។
// 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;
Button.jsx, Card.jsx, Navbar.jsx ។ ងាយស្រួលស្វែងរក និងថែទាំ!
Props — ការបញ្ជូនទិន្នន័យ
ចាប់ផ្តើមProps (Properties) ជាវិធីបញ្ជូនទិន្នន័យពី Parent Component ទៅ Child Component ។ Props អានបានតែ (Read-Only) — Child មិនអាចផ្លាស់ប្ដូរ Props បាន។
// 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
// 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
State & useState Hook
មធ្យមState គឺជាទិន្នន័យ Dynamic ក្នុង Component ។ នៅពេល State ផ្លាស់ប្ដូរ React នឹង Re-render Component ដោយស្វ័យប្រវត្តិ។ យើងប្រើ useState Hook ដើម្បីប្រកាស State ។
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
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> ); }
count = count + 1 ❌ ។ ត្រូវប្រើ Setter: setCount(count + 1) ✅
Event Handling
មធ្យមReact ប្រើ Synthetic Events ដែលមានលក្ខណៈដូច DOM Events ធម្មតា ប៉ុន្តែ Consistent ក្នុងគ្រប់ Browser ។
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> ); }
useEffect Hook
មធ្យមuseEffect ជួយឱ្យ Component ធ្វើ Side Effects — ដូចជា API Call, Timer, Event Listener ។ useEffect រត់ក្រោយ Render ។
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 ផ្លាស់ប្ដូរ |
Lists & Keys
មធ្យមដើម្បី Render List of Items ក្នុង React យើងប្រើ .map() ។ Props key ជួយ React កំណត់ Item ណាផ្លាស់ប្ដូរ — ត្រូវ Unique ក្នុង List ។
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> ); }
Controlled Forms
មធ្យមក្នុង React Form Input ត្រូវ Control ដោយ State (Controlled Component) ។ ន value ត្រូវ bind ជាមួយ State ហើយ onChange update State ។
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> ); }
Context API
ខ្ពស់Context API ដោះស្រាយបញ្ហា Prop Drilling — ការបញ្ជូន Props ច្រើនថ្នាក់។ Context អាចចែករំលែកទិន្នន័យដើម្បីប្រើក្នុង Component ទូទាំង App ។
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> ); }
Custom Hooks
ខ្ពស់Custom Hook គឺ Function ដែល Extract Logic ចេញពី Component ។ ជួយ Reuse Logic ដូចជា API Fetching, Form Handling, Local Storage ។ ឈ្មោះ Custom Hook ចាប់ផ្តើមដោយ use ។
// 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
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]; }
useReducer
ខ្ពស់useReducer ល្អជាង useState ពេល State មានភាពស្មុគស្មាញ ឬ Logic ប្រើ Action ច្រើនប្រភេទ (ដូច Redux) ។
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> ); }
useMemo & useCallback
ខ្ពស់Hooks ទាំងពីរនេះជួយ Optimize Performance ដោយ Memoize (Cache) Result ។
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 / API | Cache អ្វី | ប្រើពេល |
|---|---|---|
useMemo | Computed Value | Calculation ស្មុគ |
useCallback | Function | Pass function ទៅ Child |
React.memo | Component | Component Re-render ញឹកពេក |
React Router v6
ខ្ពស់React Router គ្រប់គ្រង Navigation ក្នុង Single Page Application (SPA) ។ ប្រើ URL ដើម្បីបង្ហាញ Component ផ្សេងៗ ដោយ Reload Page
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> ); }
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