การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ
ระบุกรณีที่ useEffect ทำให้เกิดภาพกะพริบที่มองเห็นได้ แล้วแทนที่ด้วย useLayoutEffect เพื่อแก้ไข
การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
การคำนวณการจัดวางซ้ำซ้อนคืออะไร
การคำนวณการจัดวางซ้ำซ้อนเกิดขึ้นเมื่อ JavaScript สลับไปมาระหว่างการอ่านคุณสมบัติ DOM และการเขียนลง DOM ภายในลูป การอ่านแต่ละครั้งหลังการเขียนจะบังคับให้เบราว์เซอร์คำนวณการจัดวางใหม่แบบซิงโครนัสเพื่อส่งคืนค่าที่ถูกต้อง สิ่งนี้อาจเปลี่ยนการคำนวณการจัดวางที่ควรเกิดขึ้นเพียงครั้งเดียวให้กลายเป็นหลายสิบครั้ง และทำให้ประสิทธิภาพแย่ลงอย่างมาก
การรวมการอัปเดตเป็นชุดของ React ช่วยได้อย่างไร
React จะรวมการเรียกใช้ setState ทั้งหมดภายในตัวจัดการเหตุการณ์และเอฟเฟกต์ให้เป็นการเรนเดอร์ใหม่เพียงครั้งเดียว การรวมเป็นชุดตามธรรมชาตินี้ป้องกันรูปแบบอ่าน-เขียน-อ่านที่ทำให้เกิดการคำนวณการจัดวางซ้ำซ้อนภายในรอบการเรนเดอร์เดียว ใน React 18 การรวมเป็นชุดยังครอบคลุมฟังก์ชันเรียกกลับแบบอะซิงโครนัสและพรอมิสด้วย จึงช่วยลดการคำนวณการจัดวางซ้ำซ้อนจากการอัปเดตสถานะพร้อมกัน
เมื่อเกิดการกะพริบใน useEffect
การกะพริบเกิดขึ้นเมื่อ useEffect อ่าน DOM อัปเดตสถานะ ทำให้เกิดการแสดงผลใหม่ และเบราว์เซอร์วาดภาพสองครั้ง ครั้งแรกด้วยสถานะเริ่มต้น และครั้งที่สองด้วยสถานะที่แก้ไขแล้ว การวาดภาพครั้งแรกจะแวบขึ้นชั่วครู่ก่อนถูกแทนที่ ปัญหานี้เห็นได้ชัดที่สุดกับเอฟเฟกต์ที่ปรับคุณสมบัติของเค้าโครง เช่น ความสูง ความกว้าง หรือตำแหน่ง
วินิจฉัยการกะพริบด้วย DevTools
เปิด Chrome DevTools ไปที่แท็บการแสดงผลผ่านเมนูสามจุดใต้เครื่องมือเพิ่มเติม แล้วเปิดใช้ "การกะพริบของการวาดภาพ" พื้นที่ที่มีการวาดภาพซ้ำจะถูกเน้นด้วยสีเขียว หากเห็นคอมโพเนนต์กะพริบในการแสดงผลครั้งแรก แล้ววาดภาพซ้ำทันทีเป็นเค้าโครงอื่น แสดงว่าได้รับการยืนยันว่าเกิดการวาดภาพสองครั้งจากการอัปเดตสถานะที่ขับเคลื่อนด้วย useEffect
แก้การกะพริบด้วยการย้ายไปใช้ useLayoutEffect
ย้ายการอ่าน DOM และการอัปเดตสถานะที่เป็นผลจากการอ่านนั้นจาก useEffect ไปไว้ใน useLayoutEffect การวัดค่าและการอัปเดตสถานะแบบเดิมจะเกิดขึ้นพร้อมกันก่อนการวาดภาพ จากนั้น React จะแสดงผลใหม่และยืนยันการเปลี่ยนแปลงภายในช่วงเดียวกัน ทำให้เบราว์เซอร์วาดภาพเฉพาะสถานะสุดท้ายที่ถูกต้อง การกะพริบสีเขียวใน DevTools จะหายไป
รูปแบบการวาดภาพครั้งเดียว
รูปแบบที่ไม่ทำให้กะพริบคือ อ่าน DOM ใน useLayoutEffect เรียก setState พร้อมค่าที่วัดได้ ให้ React แสดงผลใหม่พร้อมกัน ยืนยัน DOM ที่แก้ไขแล้ว และให้เบราว์เซอร์วาดภาพครั้งเดียวด้วยผลลัพธ์สุดท้าย นี่เป็นรูปแบบมาตรฐานสำหรับการจัดตำแหน่งคำแนะนำเครื่องมือ ออฟเซ็ตของส่วนหัวแบบติดค้าง และการเตรียมแอนิเมชัน
กรณีใช้งาน useEffect ที่เหมาะสม
เอฟเฟกต์เกือบทั้งหมดควรอยู่ใน useEffect ได้แก่ การดึงข้อมูล ซึ่งการกะพริบระหว่างโหลดเป็นสิ่งที่ยอมรับได้และคาดหมายไว้แล้ว การสมัครรับเหตุการณ์หรือสตรีม การบันทึกข้อมูลและการวิเคราะห์ข้อมูล ตัวจับเวลา และเอฟเฟกต์ใดก็ตามที่ไม่ได้ส่งผลต่อเค้าโครงที่มองเห็นได้ทันที การใช้ useLayoutEffect มากเกินไปในกรณีที่ useEffect ก็ทำงานได้ ถือเป็นรูปแบบที่ควรหลีกเลี่ยงและส่งผลเสียต่อประสิทธิภาพ
กรณีใช้งาน useLayoutEffect ที่เหมาะสม
ควรสงวน useLayoutEffect ไว้สำหรับการวัดค่า DOM ที่นำไปใช้สร้างผลลัพธ์ด้านภาพ เช่น ตำแหน่งคำแนะนำเครื่องมือ ตรรกะตามขนาดองค์ประกอบ การคืนค่าตำแหน่งการเลื่อน และการเตรียมแอนิเมชันที่ต้องอ่านขนาดเริ่มต้น อาการที่บอกอย่างชัดเจนว่าควรเปลี่ยนมาใช้คือการเห็นเค้าโครงที่ไม่ถูกต้องกะพริบเป็นเวลาหนึ่งเฟรมในการแสดงผลครั้งแรก
เปรียบเทียบ useEffect และ useLayoutEffect ในโค้ด
ฮุกทั้งสองมีรูปแบบการรับอาร์กิวเมนต์เหมือนกันทุกประการ: useLayoutEffect(callback, deps) เทียบกับ useEffect(callback, deps) ความแตกต่างเพียงอย่างเดียวคือช่วงเวลาที่ฟังก์ชันเรียกกลับทำงาน คุณสามารถสลับระหว่างทั้งสองได้ด้วยการแก้โค้ดเพียงคำเดียว ให้เริ่มด้วย useEffect และเปลี่ยนเป็น useLayoutEffect เฉพาะเมื่อยืนยันได้แล้วว่ามีการกะพริบ
ใช้ทั้งสองแบบในคอมโพเนนต์เดียวกัน
การใช้ฮุกทั้งสองในคอมโพเนนต์เดียวกันเพื่อจัดการคนละเรื่องเป็นสิ่งที่ทำได้และพบได้ทั่วไป ตัวอย่างเช่น คอมโพเนนต์แผนภูมิอาจใช้ useLayoutEffect เพื่อวัดความกว้างของคอนเทนเนอร์และกำหนด SVG viewBox แบบพร้อมกัน จากนั้นใช้ useEffect เพื่อดึงข้อมูลแผนภูมิแบบไม่พร้อมกัน ฮุกแต่ละตัวจะจัดการเรื่องที่ช่วงเวลาการทำงานมีความสำคัญต่อเรื่องนั้น
ทดสอบการวาดภาพสองครั้ง
นอกเหนือจากการเปิดการกะพริบของการวาดภาพใน DevTools แล้ว คุณยังสามารถเพิ่มตัวนับในคอนโซลภายในคอมโพเนนต์เพื่อช่วยนับการแสดงผลได้ หากคอมโพเนนต์บันทึกคำว่า "แสดงผล" สองครั้งเมื่อติดตั้งครั้งแรก ครั้งหนึ่งด้วยสถานะเริ่มต้นและอีกครั้งด้วยค่าที่วัดได้ซึ่งแก้ไขแล้ว แสดงว่าเกิดกรณีการวาดภาพสองครั้ง การย้ายการวัดค่าไปไว้ใน useLayoutEffect ควรทำให้เหลือการบันทึกการแสดงผลเพียงครั้งเดียวหลังติดตั้ง โดยไม่นับการแสดงผลซ้ำในโหมดเข้มงวด
เมื่อควรเลือกใช้ useLayoutEffect แทน useEffect
สถานการณ์ใดคือเหตุผลที่ถูกต้องในการใช้ useLayoutEffect แทน useEffect
สรุปบทเรียน: การปั่นป่วนของเค้าโครงและการกะพริบ
การปั่นป่วนของเค้าโครงเกิดจากการสลับอ่านและเขียน DOM ไปมา การจัดกลุ่มการอัปเดตของ React ช่วยป้องกันปัญหานี้ได้เกือบทั้งหมดภายในการแสดงผล การกะพริบเกิดขึ้นเมื่อ useEffect วัดค่า DOM และอัปเดตสถานะ ทำให้เกิดการวาดภาพสองครั้ง แก้การกะพริบด้วยการย้ายการวัดค่า DOM ไปไว้ใน useLayoutEffect ส่วนกรณีอื่นให้ใช้ useEffect เป็นค่าเริ่มต้น ทั้งการดึงข้อมูล การสมัครรับข้อมูล การบันทึกข้อมูล และตัวจับเวลา
คำถามที่พบบ่อย
บทเรียน “การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ”
ระบุกรณีที่ useEffect ทำให้เกิดภาพกะพริบที่มองเห็นได้ แล้วแทนที่ด้วย useLayoutEffect เพื่อแก้ไข คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม
ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ระยะการเรนเดอร์และการคอมมิต DOM
- useLayoutEffect ทำงานเมื่อใดเทียบกับ useEffect
- การวัดองค์ประกอบ DOM ด้วย useLayoutEffect
- การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ