Skip to content

React

Getting Started

React หรือ Next.js ดี?

หากเริ่มต้นโปรเจคใหม่ nextjs.org faviconNext.js อาจเป็นตัวเลือกที่ดีกว่า เพราะมาพร้อมระบบ routing, Server-Side Rendering (SSR), และ Static Site Generation (SSG) ในตัว ช่วยให้การพัฒนาเว็บแอปพลิเคชันที่มีประสิทธิภาพและ SEO-friendly ทำได้ง่ายขึ้น แม้เพิ่งเริ่มต้นกับ react.dev faviconReact ก็สามารถเรียนรู้ผ่าน Next.js ได้เลย

คุณสมบัติReactNext.js
ประเภทไลบรารี UIเฟรมเวิร์กที่สร้างบน React 🚀
สถาปัตยกรรมClient-Side Rendering (CSR)CSR, SSR, SSG, ISR 🚀
Routingต้องใช้ไลบรารีเสริม (เช่น React Router)App Router (File-based) ✅
โครงสร้างโปรเจคยืดหยุ่นสูง ⚖️กำหนดโครงสร้างมาตรฐาน
SEOต้องตั้งค่าและจัดการเองเหมาะสมกับ SEO อย่างยิ่ง ✅
Server-Side Renderingต้องตั้งค่าเองพร้อมใช้งาน ✅
Static Site Generationต้องใช้เครื่องมือเสริม (เช่น Gatsby)พร้อมใช้งาน ✅
การตั้งค่ายืดหยุ่น แต่ต้องตั้งค่าเองเยอะมีการตั้งค่าเริ่มต้นที่ดีที่สุด ✅
เหมาะสำหรับแอปขนาดเล็ก-กลาง, SPA ✅แอปขนาดใหญ่, เว็บไซต์, E-commerce ✅
ชุมชนใหญ่มาก ✅ใหญ่และเติบโตเร็ว
เอกสารละเอียดและครอบคลุม ✅ยอดเยี่ยมและทันสมัย
การพัฒนาเร็วเร็ว (เมื่อตั้งค่าเสร็จ) ✅เร็วมาก มีเครื่องมือครบครัน
ความปลอดภัยขึ้นอยู่กับการ implementมีฟีเจอร์ความปลอดภัยในตัว ✅
การทดสอบต้องตั้งค่าเองรองรับการทดสอบในตัว (Jest, Playwright) ✅

Basic Concepts

Components (for UI)

ส่วนประกอบพื้นฐานของ React ที่ใช้สร้าง UI โดยแบ่งเป็นไฟล์ .jsx หรือ .tsx แยกกัน

ส่วนประกอบของ Components:

ประเภทของ Stateคำอธิบายตัวอย่างกรณีการใช้งาน
Propsค่าที่รับเข้ามาในคอมโพเนนต์interface Props { msg: string }ส่งข้อมูลจาก Parent ไปยัง Child component
Callback Functionsฟังก์ชันที่ส่งเป็น props เพื่อให้ Child เรียกกลับ(value: string) => voidแจ้ง Parent เมื่อมีการเปลี่ยนแปลงใน Child
children Propช่องสำหรับส่งเนื้อหา JSX/Component<Parent> <Child /> </Parent>สร้าง Component ที่มีโครงสร้างยืดหยุ่น
Context APIส่งค่าข้ามหลายระดับคอมโพเนนต์createContext() / useContext()ส่งข้อมูลระหว่าง Component ที่ซ้อนกันหลายชั้น

1. Props - ส่งข้อมูลจาก Parent ไป Child

tsx
// ตัวอย่างการใช้ Props
import ChildComponent from './ChildComponent';

function ParentComponent() {
  // ข้อมูลที่จะส่งเป็น props
  const message = 'สวัสดีจาก Parent';

  return (
    // ส่ง props ชื่อ msg ไปยัง ChildComponent
    <ChildComponent msg={message} />
  );
}
tsx
// กำหนดประเภทของ props ที่จะรับ
interface Props {
  msg: string;
}

// รับและแสดง props ที่ชื่อ msg
function ChildComponent({ msg }: Props) {
  return <div>{msg}</div>;
}

2. Callback Functions - ส่งเหตุการณ์จาก Child ไป Parent

tsx
// ตัวอย่างการใช้ Callback
interface Props {
  onUpdate: (value: string) => void;
}

function ChildComponent({ onUpdate }: Props) {
  const newValue = 'ข้อมูลที่อัปเดตแล้ว';

  return (
    // เมื่อคลิกปุ่มจะเรียกฟังก์ชัน onUpdate ที่รับมาจาก props
    <button onClick={() => onUpdate(newValue)}>อัปเดต</button>
  );
}
tsx
import ChildComponent from './ChildComponent';

function ParentComponent() {
  // ฟังก์ชันที่ทำงานเมื่อได้รับ event 'update'
  const handleUpdate = (value: string) => {
    console.log('ได้รับค่า:', value);
  };

  return (
    // ส่งฟังก์ชัน handleUpdate เป็น prop 'onUpdate' ไปยัง Child
    <ChildComponent onUpdate={handleUpdate} />
  );
}

3. children Prop - ส่งเนื้อหา JSX/Component

tsx
import React from 'react';

interface Props {
  children: React.ReactNode;
}

function BaseLayout({ children }: Props) {
  return (
    <div className="container">
      <header>
        {/* สามารถแยก header เป็น prop เฉพาะได้ หรือใช้ children */} 
      </header>
      <main>
        {children} {/* Default slot equivalent */}
      </main>
    </div>
  );
}
tsx
import BaseLayout from './BaseLayout';

function ParentComponent() {
  return (
    <BaseLayout>
      <h1>Page Title</h1>
      <p>Main content goes here</p>
    </BaseLayout>
  );
}

4. Context API - ส่งค่าข้ามหลายระดับ Component

tsx
import { createContext } from 'react';

export const ThemeContext = createContext('light'); // Default value 'light'
tsx
import { ThemeContext } from './theme-context';
import ChildComponent from './ChildComponent';

function RootComponent() {
  return (
    <ThemeContext.Provider value="dark">
      <ChildComponent />
    </ThemeContext.Provider>
  );
}
tsx
import { useContext } from 'react';
import { ThemeContext } from './theme-context';

function DeeplyNestedChild() {
  const theme = useContext(ThemeContext);

  return <div className={theme}>...</div>;
}

Events (for User Interactions)

รูปแบบReactคำอธิบายกรณีการใช้งาน
Native EventsonClick, onChangeEvent ปกติของ DOMการจัดการคลิกปุ่ม, การเปลี่ยนแปลง input
Custom Eventsใช้ callback propsการส่ง event จาก child ไป parentเมื่อต้องการให้ child component แจ้งเหตุการณ์ไปยัง parent
Event Modifiersต้องเขียน logic เองการปรับเปลี่ยนพฤติกรรม eventเมื่อต้องการป้องกันการ submit form, หยุดการ bubbling ของ event
tsx
function Button() {
  const handleClick = () => console.log('Clicked!');
  
  return (
    <>
      <button onClick={handleClick}>Click Me</button>
      <input onChange={(e) => console.log(e.target.value)} />
    </>
  );
}
tsx
function Child({ onAction }: { onAction: (value: string) => void }) {
  return (
    <button onClick={() => onAction('Hello')}>
      Trigger Action
    </button>
  );
}

function Parent() {
  const handleAction = (value: string) => {
    console.log(`Action with value: ${value}`);
  };
  
  return <Child onAction={handleAction} />;
}
tsx
function Form() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault(); // แทน .prevent modifier
    e.stopPropagation(); // แทน .stop modifier
    console.log('Form submitted');
  };
  
  return <form onSubmit={handleSubmit}>...</form>;
}

State (for Component Data)

Hookคำอธิบายกรณีการใช้งาน
useStateสำหรับ state ง่ายๆการนับ, สถานะ toggle, ข้อมูลแบบง่าย
useReducerสำหรับ state ที่ซับซ้อนForm state, state machine
useContextสำหรับ global stateTheme, การตั้งค่าทั่วไป
tsx
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
    </div>
  );
}
tsx
const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}
tsx
const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  const theme = useContext(ThemeContext);
  return (
    <div style={{ 
      background: theme === 'dark' ? '#333' : '#FFF',
      color: theme === 'dark' ? '#FFF' : '#333'
    }}>
      Current theme: {theme}
    </div>
  );
}

Hooks (for Reusing Logic)

React มี built-in hooks ให้ใช้งานหลายตัว และยังสามารถสร้าง custom hooks ของตัวเองได้

Built-in Hooks

Hookคำอธิบายกรณีการใช้งานหมวดหมู่
react.dev faviconuseStateบันทึกและอัปเดต state ใน functional componentการจัดการ state ระดับ componentState Management
react.dev faviconuseEffectดำเนินการ side effects ใน functional componentการ fetch ข้อมูล, การติดตั้ง event listenersSide Effects
react.dev faviconuseMemoMemoize ค่าการคำนวณที่ซับซ้อนPerformance
react.dev faviconuseCallbackMemoize functionการส่งฟังก์ชันเป็น propsPerformance
react.dev faviconuseRefเก็บค่าที่ไม่ทำให้ re-renderอ้างอิง DOM, เก็บค่า previousDOM Access
react.dev faviconuseContextเข้าถึง context value จาก providerTheme, การตั้งค่าทั่วไปContext
react.dev faviconuseReducerจัดการ state ที่ซับซ้อนForm state, state machineState Management
react.dev faviconuseTransitionจัดการการอัปเดตที่ไม่ได้เร่งด่วนการโหลดข้อมูลแบบไม่บล็อก UIPerformance
react.dev faviconuseDeferredValueเลื่อนการอัปเดต UIการค้นหาที่มีการพิมพ์บ่อยๆPerformance
react.dev faviconuseIdสร้าง ID ที่ไม่ซ้ำกันForm labels, ARIA attributesDOM Access
react.dev faviconuseSyncExternalStoreการใช้งานกับ external storesการเชื่อมต่อกับ Redux, ZustandState Management
react.dev faviconuseInsertionEffectสำหรับ CSS-in-JSS librariesการ inject style ที่ runtimeDOM Access

Custom Hooks

เราสามารถสร้าง hooks ของตัวเองได้โดยการรวม built-in hooks เข้าด้วยกัน

tsx
export function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  
  const increment = () => setCount(c => c + 1);
  const decrement = () => setCount(c => c - 1);
  
  return { count, increment, decrement };
}
tsx
function Counter() {
  const { count, increment } = useCounter();
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

Lifecycle / Effects (with Hooks)

วงจรชีวิตของคอมโพเนนต์และการจัดการ side effects ด้วย useEffect

Hookคำอธิบายกรณีการใช้งาน
useEffect(() => { return () => {} }, [])ลบ event listeners, ยกเลิก timers/subscriptionsการยกเลิกการอัปเดตเมื่อ component ถูกถอดออก
useEffect(() => {}, [dep])ทำงานเมื่อ dependency dep เปลี่ยนแปลงการอัปเดตเมื่อข้อมูลเปลี่ยนแปลง
useLayoutEffectทำงานกับ DOM ทันทีหลัง render แต่ก่อน paintการอัปเดต DOM หลัง render
tsx
useEffect(() => {
  console.log('Component mounted');
  
  return () => {
    console.log('Component unmounted');
  };
}, []);
tsx
useEffect(() => {
  console.log('Value changed:', value);
}, [value]);
tsx
useLayoutEffect(() => {
  const rect = elementRef.current?.getBoundingClientRect();
  console.log('Element size:', rect);
});

Styling (for CSS)

การจัดการสไตล์และ CSS ใน React Components

วิธีการคำอธิบายเมื่อไหร่ที่ควรใช้
CSS ModulesImport ไฟล์ .module.css สไตล์จะมีผลเฉพาะที่วิธีมาตรฐานสำหรับสไตล์เฉพาะคอมโพเนนต์
Utility FrameworksTailwind/UnoCSS คลาส utility แบบ atomicการสร้างเร็ว, โปรเจคขนาดเล็ก-กลาง
CSS-in-JSStyled Components, Emotion เขียน CSS ใน JSการสร้างสไตล์แบบไดนามิกที่ซับซ้อน
tsx
function MyButton() {
  return (
    <div className="p-4 text-red-500 hover:text-blue-500 transition">
      <button className="px-4 py-2 bg-blue-500 rounded text-white">
        Click Me
      </button>
    </div>
  );
}
tsx
import clsx from 'clsx';
import { useState } from 'react';

function DynamicComponent() {
  const [isError, setIsError] = useState(true);
  const [isImportant, setIsImportant] = useState(false);

  return (
    <div 
      className={clsx(
        'base-class',
        isError && 'text-red-500',
        isImportant && 'font-bold'
      )}
    >
      Dynamic Content
    </div>
  );
}

JSX (for Rendering)

ไวยากรณ์พื้นฐานใน JSX ของ React สำหรับการเรนเดอร์

Control Flow

แนวคิดตัวอย่างกรณีการใช้งาน
Conditional Rendering{show && <div>...</div>}การแสดงผลแบบมีเงื่อนไข
List Renderingitems.map(item => <li>...</li>)การแสดงรายการข้อมูล
Dynamic AttributesclassName={isActive ? 'active' : ''}การกำหนด attribute แบบไดนามิก
Event HandlingonClick={handleClick}การจัดการเหตุการณ์
tsx
function Conditional({ showMessage, isVisible }) {
  return (
    <div>
      {showMessage && <p>This appears when showMessage is true</p>}
      {isVisible ? <div>Visible</div> : <div>Hidden</div>}
    </div>
  );
}
tsx
function List({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={item.id}>
          {index + 1}. {item.name}
        </li>
      ))}
    </ul>
  );
}
tsx
import clsx from 'clsx';

function DynamicStyles({ isActive, hasError, size }) {
  return (
    <div 
      className={clsx({ active: isActive, 'text-red': hasError })}
      style={{ fontSize: `${size}px` }}
    >
      Dynamic Styles
    </div>
  );
}
tsx
function InteractiveButton() {
  const handleClick = () => console.log('Clicked');
  const onHover = () => console.log('Hovered');
  const handleSubmit = (e) => e.preventDefault();

  return (
    <button 
      onClick={handleClick}
      onMouseOver={onHover}
      onSubmit={handleSubmit}
    >
      Interactive Button
    </button>
  );
}

Components

แนวคิดตัวอย่างกรณีการใช้งาน
Composition (children)<Card>...</Card>การประกอบคอมโพเนนต์
Conditional Rendering{currentView === 'A' ? <CompA /> : <CompB />}การสลับคอมโพเนนต์
Animation Libraries<FramerComponent>เอฟเฟกต์การเปลี่ยนภาพ
tsx
// Parent
function App() {
  return (
    <Card title="Custom Header">
      <p>Default Content</p>
    </Card>
  );
}

// Child (Card.tsx)
function Card({ title, children }) {
  return (
    <div>
      <h1>{title}</h1>
      {children}
    </div>
  );
}
tsx
import { useState } from 'react';
import Home from './Home';
import Profile from './Profile';

function App() {
  const [currentView, setCurrentView] = useState('Home');

  return currentView === 'Home' ? <Home /> : <Profile />;
}
tsx
import { motion } from 'framer-motion';

function FadingComponent({ isVisible }) {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: isVisible ? 1 : 0 }}
      transition={{ duration: 0.5 }}
    >
      I fade in and out
    </motion.div>
  );
}

APIs

React Core API

API หลักของ React สำหรับการสร้างและจัดการ component

APIคำอธิบายกรณีการใช้งานหมวดหมู่
react.dev faviconuseState()บันทึกและอัปเดต state ใน functional componentการจัดการ state ระดับ componentState Management
react.dev faviconuseEffect()ดำเนินการ side effects ใน functional componentการ fetch ข้อมูล, การติดตั้ง event listenersSide Effects
react.dev faviconuseContext()เข้าถึง context value จาก providerการแชร์ข้อมูลระหว่างหลาย componentContext
react.dev faviconuseReducer()จัดการ state ที่ซับซ้อนการจัดการ state ที่มี logic ซับซ้อนState Management
react.dev faviconuseMemo()Memoize ค่าเพื่อป้องกันการคำนวณซ้ำเพิ่มประสิทธิภาพเมื่อมีค่าที่คำนวณหนักPerformance
react.dev faviconuseCallback()Memoize function เพื่อป้องกันการสร้างใหม่เพิ่มประสิทธิภาพเมื่อส่ง callback ไปยัง child componentsPerformance
react.dev faviconmemo()ป้องกันการ re-render เมื่อ props ไม่เปลี่ยนแปลงเพิ่มประสิทธิภาพสำหรับ component ที่ render บ่อยPerformance

React DOM

API สำหรับการทำงานกับ DOM ในแอปพลิเคชัน React

APIคำอธิบายกรณีการใช้งานหมวดหมู่
react.dev faviconrender()แสดงผล React element เข้าไปใน DOMการแสดงผลแอป React ในเบราว์เซอร์Rendering
react.dev faviconhydrate()เหมือน render() แต่สำหรับเนื้อหาที่แสดงผลจากฝั่งเซิร์ฟเวอร์การทำให้หน้า SSR ทำงานแบบไดนามิกSSR
react.dev faviconcreatePortal()แสดงผล children ใน DOM node นอกลำดับชั้น parentModal, Tooltip, หรือ popup ที่ต้องแสดงเหนือองค์ประกอบอื่นAdvanced DOM
react.dev faviconunmountComponentAtNode()ลบ React component ที่ถูก mount ออกจาก DOMการทำ cleanup เมื่อปิดแอปหรือเปลี่ยนหน้าLifecycle
react.dev faviconfindDOMNode()หา DOM node ของ class component instanceใช้เมื่อต้องการเข้าถึง DOM โดยตรง (ไม่แนะนำให้ใช้บ่อย)DOM Access
react.dev faviconcreateRoot()สร้าง root สำหรับ concurrent rendering (React 18+)การตั้งค่าแอป React 18 แบบใหม่Concurrent Mode
react.dev faviconhydrateRoot()สร้าง root สำหรับ hydrating เนื้อหาจากเซิร์ฟเวอร์ (React 18+)การ hydrate แอป React 18 ที่แสดงผลจากเซิร์ฟเวอร์Concurrent Mode

Last updated: