Skip to content

React Performance Best Practices

การปรับปรุงประสิทธิภาพ (Performance) ใน React ช่วยให้แอปพลิเคชันของคุณลื่นไหล ตอบสนองไว และประหยัดทรัพยากร


ทำไม Performance ถึงสำคัญ?

  • ผู้ใช้คาดหวังว่า UI จะตอบสนองเร็ว
  • แอปที่ช้า = ประสบการณ์ใช้งานแย่ (User Experience)
  • ประหยัด resource ทั้งฝั่ง client และ server

วัดก่อนปรับ (Measure before Optimize)

  • อย่า optimize โดยไม่รู้จุดอ่อน ใช้ DevTools, React Profiler, Lighthouse ตรวจสอบก่อน
  • ดูเวลาตอบสนอง, จำนวน re-render, ขนาด bundle, FPS

เทคนิคปรับปรุง Performance ที่สำคัญ

1. ใช้ React.memo ให้ถูกจุด

  • React.memo ช่วยป้องกันการ re-render ที่ไม่จำเป็นของ functional component
  • ใช้กับ component ที่รับ props เหมือนเดิมบ่อย ๆ

ตัวอย่างที่ดี

tsx
const ExpensiveList = React.memo(function ExpensiveList({ items }) {
  // ...render list
});

ตัวอย่างที่ไม่ควรทำ

tsx
function ExpensiveList({ items }) {
  // ...render list
} // ❌ re-render ทุกครั้งที่ parent เปลี่ยน

2. useMemo & useCallback

  • useMemo: คำนวณค่าที่แพงและใช้ซ้ำ
  • useCallback: สร้างฟังก์ชันที่ไม่เปลี่ยน reference ถ้า dependency ไม่เปลี่ยน

ตัวอย่างที่ดี

tsx
const filtered = useMemo(() => items.filter(...), [items]);
const handleClick = useCallback(() => { ... }, [dep]);

ตัวอย่างที่ไม่ควรทำ

tsx
const filtered = items.filter(...); // ❌ คำนวณใหม่ทุก render
const handleClick = () => { ... };  // ❌ ฟังก์ชันใหม่ทุก render

3. จัดการ State ให้เหมาะสม

  • State ที่เปลี่ยนบ่อยควรอยู่ใกล้ component ที่ใช้ (local state)
  • อย่าโยน state ขึ้นสูงเกินจำเป็น (avoid unnecessary lifting)
  • ใช้ global state เฉพาะกรณีที่จำเป็นจริง ๆ

ตัวอย่างที่ดี

tsx
function List() {
  const [selected, setSelected] = useState(null); // local state
}

ตัวอย่างที่ไม่ควรทำ

tsx
// State อยู่ที่ parent สูงเกินไป ทำให้ลูก re-render ทั้งหมด

4. การแบ่ง Component (Splitting)

  • แบ่ง UI ใหญ่ ๆ ออกเป็น component ย่อย ๆ
  • ช่วยให้ re-render เฉพาะส่วนที่จำเป็น

ตัวอย่างที่ดี

tsx
<Page>
  <Sidebar />
  <MainContent />
</Page>;

5. Lazy Loading & Code Splitting

  • ใช้ React.lazy, Suspense โหลด component เฉพาะที่จำเป็น
  • ลดขนาด bundle หลัก โหลดเร็วขึ้น

ตัวอย่างที่ดี

tsx
const Chart = React.lazy(() => import("./Chart"));
<Suspense fallback={<Spinner />}>
  <Chart />
</Suspense>;

6. Optimize List Rendering

  • ใส่ key ที่ไม่ซ้ำกันใน list
  • ถ้า list ใหญ่ ใช้ virtualization (เช่น react-window, react-virtualized)

ตัวอย่างที่ดี

tsx
{
  items.map(item => <Item key={item.id} />);
}

ตัวอย่างที่ไม่ควรทำ

tsx
{
  items.map((item, i) => <Item key={i} />);
} // ❌ key ซ้ำได้

7. Suspense & Concurrent Features (React 18+)

  • ใช้ Suspense ช่วยจัดการ loading state
  • ใช้ startTransition สำหรับงานที่ไม่เร่งด่วน

ตัวอย่าง

tsx
import { startTransition } from "react";

startTransition(() => {
  setInputValue(newValue);
});

8. หลีกเลี่ยงการสร้าง object/array ใหม่ใน props

  • ถ้า props เป็น object/array ที่สร้างใหม่ทุกครั้ง จะทำให้ลูก re-render ตลอด

ตัวอย่างที่ดี

tsx
const config = useMemo(() => ({ theme }), [theme]);
<MyComponent config={config} />;

ตัวอย่างที่ไม่ควรทำ

tsx
<MyComponent config={{ theme }} />; // ❌ object ใหม่ทุก render

Tools สำหรับตรวจสอบ Performance

  • React DevTools (Profiler tab)
  • Chrome DevTools
  • Lighthouse
  • why-did-you-render (library สำหรับ debug re-render)

Checklist สรุป

  • [ ] วัด performance ก่อน optimize
  • [ ] ใช้ React.memo, useMemo, useCallback อย่างเหมาะสม
  • [ ] จัดการ state ให้เหมาะสม (local > global)
  • [ ] แบ่ง component และใช้ lazy loading
  • [ ] optimize การ render list
  • [ ] ใช้ Suspense/Concurrent features ถ้าเหมาะสม
  • [ ] ตรวจสอบด้วย DevTools/Profiler

การ optimize performance ใน React ไม่ใช่แค่เรื่องเทคนิค แต่คือ mindset ที่ต้องวัดก่อนปรับ และเลือกใช้เทคนิคที่เหมาะกับปัญหาจริง ๆ เท่านั้น