❖ 1. ស្គាល់ដំបូងអំពី React
1.1 React គឺជាអ្វី
React ជា Library JavaScript (មិនមែន Framework ពេញលេញដូច Angular) បង្កើតដោយ Facebook សម្រាប់ស្ថាបនាចំណុចប្រទាក់អ្នកប្រើប្រាស់ (UI) ដោយបំបែកជា "Component" តូចៗ ដែលអាចប្រើឡើងវិញបាន ជំនួសឲ្យសរសេរ DOM Manipulation ដោយផ្ទាល់ដៃដូច JavaScript ធម្មតា។
1.2 ការដំឡើង React
| វិធី | ការប្រើប្រាស់ |
|---|---|
| Vite (ណែនាំ) | npm create vite@latest my-app -- --template react |
| Create React App | npx 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.jsx | Component ចម្បងរបស់ 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>;
<div> ឬ <></> Fragment បើមានច្រើនជាមួយគ្នា)។2.2 ការបញ្ចូល JavaScript ចូល JSX
ប្រើវង់ក្រចកមូល { } ដើម្បីបញ្ចូលកន្សោម (expression) JavaScript ណាមួយចូលក្នុង JSX។
function Welcome() {
const name = "សុភា";
return <h1>សួស្តី {name}!</h1>;
}
2.3 ភាពខុសគ្នារវាង JSX Attribute និង HTML Attribute
| HTML | JSX | ហេតុអ្វី |
|---|---|---|
| class | className | class ជា Keyword រក្សាទុកក្នុង JavaScript |
| for | htmlFor | for ក៏ជា Keyword រក្សាទុកដែរ |
| onclick | onClick | JSX ប្រើ 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>
);
}
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>
);
}
❖ 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 |
| setCount | Function សម្រាប់កំណត់តម្លៃ State ថ្មី |
| useState(0) | តម្លៃដំបូង (Initial Value) របស់ 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>
);
}
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>
);
}
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;
លំហាត់អនុវត្ត
- បន្ថែម Counter បង្ហាញ "ចំនួនកិច្ចការនៅសល់" (Task ដែលមិនទាន់ done) ក្នុង Todo App ខាងលើ។
- បន្ថែមប៊ូតុង "សម្អាតកិច្ចការដែលធ្វើរួច" ដែលលុប Task ដែល
done: trueទាំងអស់ក្នុងម្ដង។ - ប្រើ
useEffectរក្សាទុកបញ្ជី Task ទៅlocalStorageរាល់ពេល Task ផ្លាស់ប្តូរ ដើម្បីកុំឲ្យបាត់ពេល Reload ទំព័រ។ - បន្ថែម Filter Button (ទាំងអស់ / កំពុងធ្វើ / ធ្វើរួច) ដើម្បីបង្ហាញ Task តាមស្ថានភាព។