React life cycle แบบละเอียด image

React life cycle แบบละเอียด

หนึ่งในเรื่องที่ซับซ้อนที่สุดเรื่องหนึ่งของ React ที่ทำให้ผู้เริ่มต้นใหม่รู้สึกมีกำแพงสูงหลายฟุตอยู่ด้านหน้าก็คงไม่พ้นเรื่อง Life cycle ที่แม้แต่กับคนที่มีความคุ้นชินกับ React มานานหลายปีก็ยังคงตกหลุมข้อผิดพลาดได้ง่าย ๆ แต่สำหรับในบทความนี้เราจะมาพูดถึงการทำงาน กฏเกณฑ์ และ เงื่อนไขในการทำงานต่าง ๆ เหล่านี้จาก Zero ไป Hero ทั้งหมดกัน

Aug 21,2024
Supakorn Netsuwan🪶

Technical

React

Next.js

Thai

Table of contents

React life cycle

วงจรชีวิต เป็นคำที่มีอยู่ในทุกวงการ คุณอาจจะเคยเรียนวิชาชีวะ วิชาเคมี ใด ๆ ก็แล้วแต่ก็มักจะมีคำนี้อยู่ในทุกอนูของเนื้อหา

วงจรชีวิตมีความหมายว่า การเวียนว่ายตายเกิด ลักษณาการของชีวิตที่มีพัฒนาการเป็นขั้น ๆ ไปตามลำดับและในที่สุดก็จะเวียนมาบรรจบณ จุดเริ่มต้นใหม่ แล้วเวียนซ้ำต่อไปอีก เช่น ผีเสื้อออกไข่ แล้วไข่กลายเป็นตัวหนอน หนอนกลายเป็นดักแด้ ดักแด้กลายเป็นผีเสื้อแล้วผีเสื้อก็ออกไข่

สำหรับ React เองก็มีวงจรชีวิตของมันเองเช่นกัน ตั้งแต่ Component เริ่ม Mount, Update และ Unmount เราจะมาเจาะรายละเอียดเหล่านี้กันในบทความนี้

Mount

เป็นกระบวนการแรกสุดที่เกิดขึ้น คือการ Render HTML Elements ออกมาบนหน้าจอของผู้ใช้งาน เริ่มจากผู้ใช้ร้องขอเว็บไซต์แล้ว Browser จะทำการส่ง Request ไปที่ Web server จากนั้น​ Web server ก็จะทำการส่ง Response กลับเป็นไฟล์ Resources ต่าง ๆ รวมถึง HTML template, CSS, Images และ ไปยัง Client browser ที่ร้องขอ ทำให้ในช่วงแรกของการโหลดเว็บไซต์ผู้ใช้จะเห็นหน้าขาวว่างได้ (Blank page) เนื่องจากไฟล์ HTML ที่ถูกส่งมาไม่ได้ผ่านการ Pre-rendering มาก่อน ซึ่งแตกต่างจาก Server Side Rendering (SSR) / Static Site Generation (SSG) ที่สามารถส่ง Pre-rendered HTML มาได้จึงช่วยลดภาระการทำงานของ Client browser ได้ จากนั้นเมื่อ Resources ต่าง ๆ ถูกส่งมาที่ Web client เสร็จแล้วก็จะเริ่มกระบว Rendering ดังต่อไนปี้

กระบวนการเม้าท์ทิ่ง (Component mounting)

  1. JavaScript initialization
  2. State & Hooks intialization
  3. Return JSX
  4. Insert DOM Node
  5. Attach ref
  6. useLayoutEffect executes
  7. DOM paint
  8. useEffect executes

Update

เมื่อเข้าเงื่อนไขบางประการจะทำให้ Component อัปเดตผ่านการ Re-rendering เพื่อแสดงผล UI ที่เปลี่ยนไปยังหน้าจอของผู้ใช้งาน

  1. Context updates เมื่อมีการเรียกใช้ useContext() ภายใน Component แล้วมีการเปลี่ยนแปลงของ Context
  2. State updates จาก State ภายใน Component
  3. Prop changes เมื่อ prop(s) ที่ถูกส่งมามีการเปลี่ยนแปลง
  4. Parent re-render เมื่อ Parent component มีการ Re-rendering จาก State ภายใน

ปัจจัยทั้ง 4 ข้างต้นอาจเป็นหนึ่งในปัจจัยที่ทำให้ Component เกิดการอัปเดตได้ โดยปกติแล้ว React จะมีการ Synchronize สถานะของแอปพลิเคชันผ่าน Real DOM และ Virtual DOM

  1. Real DOM — เป็น DOM ที่แท้จริงที่ถูกแสดงผลใน Browser มีลักษณะเหมือน Tree
  2. Virtual DOM — เป็น DOM จำลองจาก Real DOM ทำงานภายใน Memory ทำหน้าที่เปรียบเทียบการเปลี่ยนแปลงสถานะของ DOM

React จะมีหน้าที่ทำให้สถานะการแสดงผล UI ของแอปพลิเคชันสอดคล้องและสดใหม่อยู่ตลอดเวลา เมื่อมีการเปลี่ยนแปลงของ State แล้ว React จะมีกระบวนการ Reconciliation ที่เมื่อเสร็จสิ้นกระบวนการดังกล่าว React ก็จะรู้ว่า อ๋ออออ "เราต้องมีการ Re-render component นี้นะเพื่อเปลี่ยนแปลงการแสดงผลของ UI แต่ถ้าเป็นส่วนอื่นก็ไม่ต้องไปยุ่ง" ทำให้การ Re-rendering เกิดขึ้นเฉพาะใน Sub tree ของ DOM ที่จำเป็นเท่านั้น ✨

กระบวนการอัปเดต (Component updating)

  1. JavaScript initialization
  2. State & Hooks initialization
  3. Return JSX
  4. Update DOM node
  5. Unset DOM ref
  6. useLayoutEffect cleanups
  7. Attach ref
  8. useLayoutEffect executes
  9. DOM paint
  10. useEffect cleanups
  11. useEffect executes

Unmount

React Life cycle ก็อาจเหมือนกับวัฏจักรชีวิตตรงที่เมื่อมีเกิดก็มีจบ (ฮา) เมื่อ Component ใด ๆ ต้องถูกถอดออกจาก DOM (คล้ายกับการใช้ document.removeChild() สำหรับการทำ ในแบบเดิม ๆ) แต่ความแตกต่างคือเมื่อ Component ถูกถอดออกหรือ Unmount จะเกิดกระบวนการ Re-rendering อีกหนึ่งรอบเพื่อให้การนำส่วนดังกล่าวออกเกิดในการแสดงผลรอบถัดไป และ ที่สำคัญก้คือยังช่วยเปิดโอกาสให้เราสามารถทำ Clean up ได้ โดยกระบวนการ Unmounting จะมีดั่งต่อไปนี้

กระบวการอันเม้าท์ (Component unmounting)

  1. useLayoutEffect cleanups
  2. Unset DOM ref
  3. remove DOM node
  4. useEffect cleanups

Virtual DOM และ Reconciliation

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

เมื่อ React ต้องการที่จะเปลี่ยนแปลง DOM node จะได้ไม่ต้องเปลี่ยนแปลงโดยตรงแต่ให้ทำผ่านการเปรียบเทียบของ Virtual DOM เก่ากับของใหม่ว่าส่วนใดที่จำเป็นต้องอัปเดตใหม่หรือมีการเปลี่ยนแปลง (ด้วยกระบวนการ Reconciliation) ส่วนใดที่ไม่สามารถอัปเดตได้แต่ต้องทำการ Unmount ใหม่ทั้งหมดแล้วค่อย Mount ใหม่ในภายหลัง

tldr; Virtual DOM เป็นข้อมูลที่ Reflect มาจาก Real DOM ซึ่งทำงานอยู่บน Memory ช่วยทำให้การเปรียบเทียบส่วนที่ต้องเปลี่ยนแปลงเร็วขึ้น

  1. Mounting — UI และ Components ทำการ Render เป็นครั้งแรกตามที่ได้อธิบายไป
  2. Virtual DOM snapshot is created — มีการเก็บโครงสร้างของ DOM ปัจจุบันผ่าน Memory เพื่อใช้เปรียบเทียบ
  3. State changed / Parent component re-render — เมื่อเกิดการเปลี่ยนแปลงของ Internal state หรือ Parent component มีการ Re-render
  4. New fiber, Virtual DOM created — สร้าง Virtual DOM ใหม่ โดยจะมีสถานะเป็น Fresh virtual DOM
  5. Virtual DOM is compared — เกิดการเทียบ Virtual DOM ปัจจุบันกับ Virtual DOM ใหม่ที่เปลี่ยนแปลงไป
  6. Reconciliation — React หาวิธีในการแก้ไข Real DOM ด้วยวิธีที่ดีที่สุดและเฉพาะ Component ที่จำเป็นที่สุด
  7. Re-render (Update) — ทำการ Commit สิ่งที่ต้องเปลี่ยนแปลงในรูปแบบ Bash เพื่ออัปเดตการแสดงผลผ่านการ Re-rendering