0Pricing
React Academy · บทเรียน

การแยก Context เพื่อลดการเรนเดอร์ซ้ำ

แยกค่าที่เปลี่ยนแปลงบ่อยออกจากค่าที่คงที่ไว้ใน Context คนละชุด

การแยก Context เพื่อลดการเรนเดอร์ซ้ำ เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

ยินดีต้อนรับ

ในบทเรียนนี้ คุณจะเรียนรู้การแยก React Context ออกเป็นผู้ให้บริการหลายตัว เพื่อให้เกิดการเรนเดอร์ใหม่น้อยลงเมื่อมีการเปลี่ยนแปลงเพียงบางส่วนของค่าบริบท

ปัญหาการเรนเดอร์ใหม่เมื่อใช้บริบท

คอมโพเนนต์ทุกตัวที่เรียกใช้ useContext(MyCtx) จะเรนเดอร์ใหม่เมื่อส่วนใดก็ตามของค่าบริบทเปลี่ยนแปลง — แม้แต่ส่วนที่คอมโพเนนต์ใช้งานจะไม่ได้เปลี่ยนก็ตาม บริบทขนาดใหญ่เพียงตัวเดียวอาจทำให้เกิดการเรนเดอร์ใหม่ที่ไม่จำเป็นจำนวนมาก

การแยกตามความถี่ในการอัปเดต

แยกค่าที่เปลี่ยนแปลงบ่อยออกจากค่าที่เปลี่ยนแปลงไม่บ่อย ใส่แต่ละกลุ่มไว้ในบริบทของตนเอง คอมโพเนนต์ผู้ใช้จะสมัครรับเฉพาะบริบทที่ต้องการ
const ThemeCtx = createContext('light');
const UserCtx = createContext(null);
// theme changes rarely; user changes on login/logout — same frequency is fine
// but notifCount changes every second — split it out!

การแยกบริบทข้อมูลและการส่งคำสั่ง

รูปแบบที่ใช้กันทั่วไปคือแยกบริบทหนึ่งสำหรับข้อมูลสถานะ (เรนเดอร์ใหม่ทุกครั้งที่มีการเปลี่ยนแปลง) และอีกบริบทหนึ่งสำหรับฟังก์ชัน dispatch/setter (คงที่และไม่ทำให้คอมโพเนนต์ผู้ใช้เรนเดอร์ใหม่) คอมโพเนนต์ที่ใช้เฉพาะ dispatch จะไม่เรนเดอร์ใหม่เมื่อข้อมูลเปลี่ยนแปลง
const CountCtx = createContext(0);
const SetCountCtx = createContext(() => {});

function Provider({ children }) {
  const [count, setCount] = useState(0);
  return (
    <CountCtx.Provider value={count}>
      <SetCountCtx.Provider value={setCount}>
        {children}
      </SetCountCtx.Provider>
    </CountCtx.Provider>
  );
}

การจดจำค่าบริบทการส่งคำสั่ง

ฟังก์ชัน setter จาก useState คงที่ (เป็นการอ้างอิงเดิมในทุกการเรนเดอร์) ดังนั้นค่าบริบทการส่งคำสั่งจึงไม่เปลี่ยนแปลง แต่หากคุณคำนวณออบเจ็กต์ของ actions ให้ห่อออบเจ็กต์นั้นด้วย useMemo
const actions = useMemo(() => ({
  increment: () => setCount(c => c + 1),
  reset: () => setCount(0),
}), []); // stable — empty deps

ผู้ให้บริการแบบซ้อนกัน

ซ้อนผู้ให้บริการหลายตัวไว้ในลำดับชั้นคอมโพเนนต์ คอมโพเนนต์ผู้ใช้นำเข้าและใช้เฉพาะบริบทที่ต้องการ ทำให้ขอบเขตการสมัครรับแคบลง
function App() {
  return (
    <AuthProvider>
      <ThemeProvider>
        <NotificationsProvider>
          <Router />
        </NotificationsProvider>
      </ThemeProvider>
    </AuthProvider>
  );
}

วิเคราะห์ประสิทธิภาพก่อนแยกบริบท

วิเคราะห์ประสิทธิภาพด้วย React DevTools ก่อนแยกบริบทเสมอ การเรนเดอร์ใหม่ที่ไม่จำเป็นจะเป็นปัญหาก็ต่อเมื่อใช้ทรัพยากรมาก อย่าออกแบบบริบทซับซ้อนเกินความจำเป็นหากการเรนเดอร์ใหม่ทำได้รวดเร็ว

ข้อแลกเปลี่ยนของการแยกบริบท

บริบทที่มากขึ้นหมายถึงมีผู้ให้บริการในลำดับชั้นคอมโพเนนต์มากขึ้น ซึ่งเพิ่มภาระในการทำความเข้าใจ แยกบริบทเมื่อการวิเคราะห์ประสิทธิภาพแสดงให้เห็นว่ามีปัญหาด้านประสิทธิภาพเท่านั้น ไม่ใช่แยกไว้ล่วงหน้า

การผสานกับ React.memo

แม้จะใช้บริบทเพียงตัวเดียว การห่อคอมโพเนนต์ลูกที่ใช้ทรัพยากรมากด้วย React.memo ก็ทำให้คอมโพเนนต์เหล่านั้นเรนเดอร์ใหม่เฉพาะเมื่อพร็อพส์เปลี่ยนแปลง ไม่ใช่เมื่อบริบทเปลี่ยนแปลง วิธีนี้อาจเป็นทางเลือกที่ง่ายกว่าการแยกบริบท
const ExpensiveChild = React.memo(function({ label }) {
  return <div>{label}</div>;
}); // won't re-render on context change if label hasn't changed

useReducer + Context

ใช้ useReducer ร่วมกับบริบทเพื่อจัดการสถานะที่ซับซ้อน เก็บสถานะไว้ในบริบทหนึ่ง และฟังก์ชัน dispatch ไว้ในอีกบริบทหนึ่ง dispatch คงที่ ส่วนสถานะจะอัปเดตเมื่อมี action ทุกครั้ง

ตรวจสอบอย่างรวดเร็ว

เหตุใดการแยกสถานะและ dispatch ออกเป็นบริบทคนละตัวจึงช่วยเพิ่มประสิทธิภาพ

สรุปทบทวน

แยกบริบทตามความถี่ในการอัปเดต โดยใส่สถานะที่เปลี่ยนแปลงบ่อยไว้ในบริบทหนึ่ง และ dispatch/setter ที่คงที่ไว้อีกบริบทหนึ่ง วิเคราะห์ประสิทธิภาพก่อน แยกเฉพาะเมื่อจำเป็น และพิจารณา React.memo เป็นทางเลือกที่ง่ายกว่า

บทเรียนถัดไป

บทเรียนถัดไป: **การจดจำค่าบริบทด้วย useMemo** — คุณจะห่อออบเจ็กต์ค่าบริบทด้วย useMemo เพื่อไม่ให้คอมโพเนนต์ผู้ใช้เรนเดอร์ใหม่เมื่อข้อมูลไม่ได้เปลี่ยนแปลง

คำถามที่พบบ่อย

บทเรียน “การแยก Context เพื่อลดการเรนเดอร์ซ้ำ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การแยก Context เพื่อลดการเรนเดอร์ซ้ำ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การแยก Context เพื่อลดการเรนเดอร์ซ้ำ”

แยกค่าที่เปลี่ยนแปลงบ่อยออกจากค่าที่คงที่ไว้ใน Context คนละชุด คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “การแยก Context เพื่อลดการเรนเดอร์ซ้ำ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม

ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การแยก Context เพื่อลดการเรนเดอร์ซ้ำ
  2. การจดจำค่า Context ด้วย useMemo
  3. รูปแบบ Context Selector
  4. กรณีที่ไม่ควรใช้ Context
← กลับไปที่ React Academy