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

การสร้างคอมโพเนนต์โมดัลด้วย Portals

สร้างโมดัลที่นำกลับมาใช้ใหม่ได้และเรนเดอร์ลงใน document.body ผ่าน createPortal

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

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

ในบทเรียนนี้ คุณจะสร้างคอมโพเนนต์ Modal ที่นำกลับมาใช้ใหม่ได้ โดยใช้ React.createPortal เพื่อเรนเดอร์ลงใน document.body พร้อมรองรับการปิดเมื่อคลิกพื้นหลังทับและกดปุ่ม Escape

โครงร่างคอมโพเนนต์โมดัล

เริ่มจากโครงสร้างพื้นฐาน: คอมโพเนนต์ Modal ที่รับพร็อพ `isOpen`, `onClose` และ `children` เมื่อ `isOpen` เป็น false ให้เรนเดอร์เป็นไม่มีอะไร
function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;
  return createPortal(
    <div className="backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}

พื้นหลังทับและการหยุดการส่งต่อ

div `backdrop` ด้านนอกครอบคลุมทั้งหน้าจอ เมื่อคลิกจะเรียก `onClose` ส่วน div `modal` ด้านในเรียก `e.stopPropagation()` เพื่อไม่ให้การคลิกภายในโมดัลส่งต่อไปยังพื้นหลังทับและทำให้โมดัลปิดโดยไม่ตั้งใจ

การปิดด้วยปุ่ม Escape

เพิ่ม `useEffect` ที่รับฟังเหตุการณ์ `keydown` เมื่อกดปุ่ม Escape ขณะที่โมดัลเปิดอยู่ ให้เรียก `onClose` และนำตัวรับฟังออกตอนล้างการทำงาน
useEffect(() => {
  if (!isOpen) return;
  const handle = (e) => { if (e.key === 'Escape') onClose(); };
  document.addEventListener('keydown', handle);
  return () => document.removeEventListener('keydown', handle);
}, [isOpen, onClose]);

การป้องกันการเลื่อนของเนื้อหา

เมื่อโมดัลเปิดอยู่ โดยทั่วไปคุณจะต้องป้องกันไม่ให้หน้าที่อยู่ด้านหลังเลื่อน เพิ่มและนำ `overflow: hidden` ออกจาก `document.body` ภายใน `useEffect`
useEffect(() => {
  if (isOpen) {
    document.body.style.overflow = 'hidden';
  }
  return () => { document.body.style.overflow = ''; };
}, [isOpen]);

CSS พื้นฐานสำหรับโมดัล

พื้นหลังทับควรเป็นชั้นซ้อนแบบ fixed ที่ครอบคลุมทั้งหน้าจอ กล่องโมดัลควรอยู่กึ่งกลาง วิธีใช้ CSS ขั้นต่ำคือใช้ flexbox บนพื้นหลังทับเพื่อจัดโมดัลให้อยู่กึ่งกลาง
.backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000;
}
.modal {
  background: white;
  border-radius: 8px;
  padding: 24px;
  min-width: 320px;
}

การใช้โมดัล

ควบคุมโมดัลด้วยตัวแปรสถานะแบบบูลีนในคอมโพเนนต์แม่ ส่งพร็อพ `isOpen` และ `onClose` ไปยัง Modal และใส่เนื้อหาใด ๆ เป็น children
function App() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button onClick={() => setOpen(true)}>Open Modal</button>
      <Modal isOpen={open} onClose={() => setOpen(false)}>
        <h2>Hello from the modal!</h2>
        <button onClick={() => setOpen(false)}>Close</button>
      </Modal>
    </>
  );
}

การเพิ่มปุ่มปิดไว้ด้านใน

ควรมีปุ่มปิดที่ชัดเจนอยู่ภายในโมดัลเสมอ สำหรับผู้ใช้ที่ไม่สามารถใช้แป้นพิมพ์หรือไม่สังเกตเห็นพื้นหลังทับ ส่ง `onClose` ต่อไปยังเนื้อหาผ่าน children หรือพร็อพ

ภาพเคลื่อนไหวด้วยการเปลี่ยนผ่านของ CSS

สำหรับเอฟเฟกต์ค่อย ๆ ปรากฏ แทนที่จะคืนค่า null เมื่อปิด ให้เรนเดอร์พอร์ทัลเสมอ แต่สลับคลาส CSS ใช้การเปลี่ยนผ่านของ CSS `opacity` และ `transform` บนพื้นหลังทับ
// Toggle class based on isOpen
<div className={`backdrop ${isOpen ? 'visible' : 'hidden'}`}>

การประกอบส่วนหัวและส่วนท้ายของโมดัล

แยกโมดัลออกเป็นคอมโพเนนต์ย่อย: `Modal.Header`, `Modal.Body`, `Modal.Footer` ใช้รูปแบบคอมโพเนนต์แบบประกอบ เพื่อให้ผู้ใช้ประกอบเลย์เอาต์โมดัลได้โดยไม่ต้องรู้ชื่อคลาส

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

เหตุใดเราจึงเรียก e.stopPropagation() ในตัวจัดการ onClick ของ div โมดัลด้านใน

สรุปทบทวน

คุณสร้าง Modal ด้วย createPortal แล้ว: การคลิกพื้นหลังทับจะปิดโมดัล การกดปุ่ม Escape จะปิดโมดัล การเลื่อนเนื้อหาจะถูกล็อกขณะเปิด และ stopPropagation จะป้องกันไม่ให้การคลิกภายในโมดัลทำให้โมดัลปิด

บทถัดไป

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

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

บทเรียน “การสร้างคอมโพเนนต์โมดัลด้วย Portals” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การสร้างคอมโพเนนต์โมดัลด้วย Portals”

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

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

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

บทเรียน “การสร้างคอมโพเนนต์โมดัลด้วย Portals” ใช้เวลานานแค่ไหน

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

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

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

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

  1. React Portals คืออะไร
  2. การสร้างคอมโพเนนต์โมดัลด้วย Portals
  3. การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล
  4. คำแนะนำเครื่องมือและเมนูดรอปดาวน์ด้วย Portals
← กลับไปที่ React Academy