การวัดองค์ประกอบ DOM ด้วย useLayoutEffect
อ่านขนาด ตำแหน่ง และระยะเลื่อนขององค์ประกอบหลังจัดวางเสร็จแต่ก่อนวาดภาพ เพื่อหลีกเลี่ยงการกะพริบ
การวัดองค์ประกอบ DOM ด้วย useLayoutEffect เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
ภาพรวมของ getBoundingClientRect
element.getBoundingClientRect() ส่งคืนออบเจ็กต์ DOMRect ซึ่งมีขนาดและตำแหน่งขององค์ประกอบเมื่อเทียบกับพื้นที่แสดงผล ได้แก่ top, right, bottom, left, width และ height ฟังก์ชันนี้บังคับให้เบราว์เซอร์คำนวณการจัดวางเพื่อส่งคืนค่าที่ถูกต้อง จึงควรเรียกใช้อย่างประหยัด
ปัญหาของการอ่านค่าใน useEffect
หากคุณอ่านค่า getBoundingClientRect() ใน useEffect เบราว์เซอร์จะวาดหน้าจอไปแล้ว หากคุณตั้งสถานะตามค่าที่วัดได้ React จะเรนเดอร์ใหม่ และเบราว์เซอร์จะวาดหน้าจออีกครั้ง ผู้ใช้อาจเห็นองค์ประกอบอยู่ในตำแหน่งหรือมีขนาดไม่ถูกต้องชั่วครู่ ก่อนที่การแก้ไขจะปรากฏในการวาดหน้าจอครั้งที่สอง
เหตุผลที่ useLayoutEffect แก้ปัญหานี้ได้
การอ่านค่าที่วัดได้ใน useLayoutEffect เกิดขึ้นหลังการเปลี่ยนแปลง DOM แต่ก่อนการวาดหน้าจอ การอัปเดตสถานะใด ๆ ที่เกิดจากการวัดค่าจะทำให้ React เรนเดอร์ใหม่แบบซิงโครนัสและคอมมิต DOM ที่แก้ไขแล้ว ทั้งหมดนี้เกิดขึ้นก่อนที่เบราว์เซอร์จะวาดสิ่งใด ผู้ใช้จึงเห็นเฉพาะผลลัพธ์สุดท้ายที่ถูกต้องในการวาดหน้าจอเพียงรอบเดียว
การจัดตำแหน่งกล่องคำแนะนำ
กล่องคำแนะนำต้องปรากฏใกล้องค์ประกอบที่เรียกใช้ ให้วัดตำแหน่งขององค์ประกอบที่เรียกใช้ใน useLayoutEffect โดยใช้ getBoundingClientRect() คำนวณตำแหน่งสัมบูรณ์ของกล่องคำแนะนำ แล้วตั้งตำแหน่งนั้นในสถานะ กล่องคำแนะนำจะแสดงในตำแหน่งที่ถูกต้องตั้งแต่การวาดหน้าจอครั้งแรก โดยไม่มีการกระโดดที่มองเห็นได้จากตำแหน่งเริ่มต้นที่ไม่ถูกต้อง
แอนิเมชันองค์ประกอบ: การอ่านขนาดเริ่มต้น
หากต้องการทำแอนิเมชันองค์ประกอบจากขนาดตามธรรมชาติ (ที่ยังไม่ถูกจำกัด) ไปเป็นขนาดคงที่ คุณต้องทราบขนาดตามธรรมชาติก่อนใช้ข้อจำกัด ให้อ่านความสูงขององค์ประกอบใน useLayoutEffect ก่อนใช้รูปแบบแอนิเมชันใด ๆ เก็บค่านั้นไว้ในสถานะ แล้วใช้เป็นค่าของเฟรมหลักเริ่มต้นสำหรับการเปลี่ยนผ่านของ CSS
ความสูงของส่วนหัวแบบติดอยู่กับที่
เมื่อหน้ามีส่วนหัวแบบติดอยู่กับที่ เนื้อหาในหน้าต้องมีระยะห่างด้านบนเท่ากับความสูงของส่วนหัว เพื่อไม่ให้เนื้อหาถูกซ่อนอยู่ด้านหลัง ให้วัดความสูงของส่วนหัวใน useLayoutEffect โดยใช้รีฟ: headerRef.current.getBoundingClientRect().height ตั้งค่านี้เป็น paddingTop ให้กับกล่องเนื้อหา การจัดวางจึงถูกต้องตั้งแต่การเรนเดอร์ครั้งแรก
การอัปเดตสถานะทำให้เรนเดอร์ใหม่แบบซิงโครนัส
เมื่อคุณเรียกใช้ setState ภายใน useLayoutEffect React จะทำงานเรนเดอร์และคอมมิตรอบใหม่ทันทีในบล็อกแบบซิงโครนัสเดียวกัน การเรนเดอร์ใหม่นี้จะทำงานกับ useLayoutEffect ของมันด้วย โปรดระวังไม่ให้เกิดการวนซ้ำไม่รู้จบ โดยอัปเดตสถานะเฉพาะเมื่อค่าที่วัดใหม่แตกต่างจากค่าปัจจุบันในสถานะเท่านั้น
SSR: การวัดค่าคืนค่าเป็นศูนย์
บนเซิร์ฟเวอร์ องค์ประกอบ DOM ไม่มีอยู่จริง ดังนั้น getBoundingClientRect() อาจทำให้เกิดข้อผิดพลาดหรือคืนค่าเป็นศูนย์ ให้ป้องกัน useLayoutEffect ด้วยการตรวจสอบดังนี้: if (typeof window === 'undefined') return; สำหรับแอป SSR คุณอาจต้องเริ่มต้นด้วยขนาดตัวแทน แล้ววัดค่าอีกครั้งหลังการไฮเดรตบนฝั่งไคลเอ็นต์
ResizeObserver สำหรับการติดตามอย่างต่อเนื่อง
การวัดครั้งเดียวด้วย useLayoutEffect จะให้ขนาดในเวลาที่เมานต์ สำหรับการติดตามการเปลี่ยนแปลงขนาดขณะที่องค์ประกอบปรับขนาด เช่น จากการปรับขนาดหน้าต่าง เนื้อหาแบบไดนามิก หรือการเปลี่ยนแปลงของ CSS ให้ใช้ ResizeObserver แทน โดยจะเรียกใช้ฟังก์ชันเรียกกลับทุกครั้งที่ขนาดขององค์ประกอบเปลี่ยนแปลง จึงเหมาะกับคอมโพเนนต์ที่ปรับตามขนาดมากกว่า
การหลีกเลี่ยงการวัดค่าซ้ำซ้อน
หากเอฟเฟกต์หลายรายการต้องใช้ค่าที่วัดเดียวกัน ให้คำนวณเพียงครั้งเดียวแล้วแชร์ผ่านบริบทหรือส่งต่อเป็นคุณสมบัติ การคำนวณค่า getBoundingClientRect() เดียวกันในคำสั่งเรียกใช้ useLayoutEffect หลายรายการจะทำให้เกิดการอ่านการจัดวางแบบซิงโครนัสหลายครั้ง ซึ่งแต่ละครั้งใช้ทรัพยากรค่อนข้างมาก ควรรวมการวัดค่าเมื่อทำได้
จังหวะเวลาของรีฟกับ useLayoutEffect
รีฟจะถูกกำหนดค่าก่อนที่เอฟเฟกต์จะทำงาน เมื่อ useLayoutEffect ทำงาน จะรับประกันได้ว่า ref.current ชี้ไปยังองค์ประกอบ DOM อยู่ นี่คือเหตุผลที่รูปแบบนี้ใช้ได้: useLayoutEffect(() => { const rect = ref.current.getBoundingClientRect(); ... }, []) รีฟจะไม่เป็นค่าว่างภายในเอฟเฟกต์การจัดวางของคอมโพเนนต์ที่เมานต์แล้ว
จังหวะเวลาของ getBoundingClientRect
เหตุใดการเรียกใช้ getBoundingClientRect() ใน useLayoutEffect จึงดีกว่าการเรียกใช้ใน useEffect
สรุปบทเรียน: การวัดองค์ประกอบ DOM
ใช้ getBoundingClientRect() ใน useLayoutEffect เพื่ออ่านค่าการวัด DOM หลังการเปลี่ยนแปลงข้อมูลแต่ก่อนการวาดหน้าจอ การอัปเดตสถานะจากการวัดค่าเหล่านี้จะทำให้เกิดการเรนเดอร์ใหม่แบบซิงโครนัส ซึ่งรวมอยู่ในการวาดหน้าจอรอบเดียวกันและป้องกันการกะพริบ ป้องกัน SSR ด้วยการตรวจสอบ typeof window สำหรับการติดตามขนาดอย่างต่อเนื่อง ให้เลือกใช้ ResizeObserver
คำถามที่พบบ่อย
บทเรียน “การวัดองค์ประกอบ DOM ด้วย useLayoutEffect” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การวัดองค์ประกอบ DOM ด้วย useLayoutEffect” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การวัดองค์ประกอบ DOM ด้วย useLayoutEffect”
อ่านขนาด ตำแหน่ง และระยะเลื่อนขององค์ประกอบหลังจัดวางเสร็จแต่ก่อนวาดภาพ เพื่อหลีกเลี่ยงการกะพริบ คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การวัดองค์ประกอบ DOM ด้วย useLayoutEffect” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม
ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ระยะการเรนเดอร์และการคอมมิต DOM
- useLayoutEffect ทำงานเมื่อใดเทียบกับ useEffect
- การวัดองค์ประกอบ DOM ด้วย useLayoutEffect
- การหลีกเลี่ยงการจัดวางซ้ำและภาพกะพริบ