Використовуйте ReactDOM createPortal для створення компонентів, таких як Modal, у вашому власному стилі.

โอ้ มาย ก็อดดดด (เสียง 9Arm) ผมเพิ่งเจอว่า React มันมีตัว createPortal ในการแทรก JSX เข้าไปใน Element ที่ต้องการได้ เมื่อ Component นั้นถูก render

ในบทความนี้ ผมจะใช้ตัวอย่างด้วยการแนะนำการทำ Modal นะครับ ง่ายดี และผมจะใช้ motion-framer ร่วมเพื่อทำ Animation นะครับ

วิธีใช้งาน

สร้าง Modal Component สำหรับการเรียกใช้งาน

ขอแจ้งนิดนึง การอ้างอิงค่าของ createPortal จะเป็นแบบนี้ครับ

createPortal(children, domNode, key?)

และสำหรับไฟล์ Modal Component นั้น

ผมจะเก็บไฟล์ไว้ใน /src/components/Modal.tsx นะครับ

'use client'  

import { AnimatePresence, motion } from "motion/react"  
import { MouseEventHandler, useEffect, ReactNode } from "react"  
import { createPortal } from "react-dom"  

interface IModalComponentProps  
{  
 children: ReactNode  
 isShow: boolean  
 onClose: () => void  
}  

const Modal = ({ children, isShow, onClose }: IModalComponentProps) =>  
{  
 const handleClose: MouseEventHandler = () => (onClose && onClose())  

 useEffect(() =>  
 {  
 // อันนี้ใช้ทำลูกเล่น ขณะที่ Modal โชว์อยู่ เมื่อกดปุ่ม Esc แล้วจะปิดครับ  
 if( typeof isShow === "boolean" )  
 {  
 const onKeypressEsc = (e: KeyboardEvent) =>  
 {  
 if( e.key === "Escape" )  
 {  
 if(onClose)  
 {  
 onClose()  
 }  
 }  
 }  

 if( isShow )  
 {  
 window.addEventListener("keydown", onKeypressEsc)  

 // คืนค่าเมื่อ Modal unmount หรือถูกลบ ให้ลบ Event listener  
 return () => window.removeEventListener("keydown", onKeypressEsc)  
 }  
 }  
 },  
 [isShow, onClose])  

 // เรียกใช้งาน createPortal ตอนที่ return ให้กับฟังก์ชั่นเลยครับ  
 return createPortal(  

 {  
 isShow && (  

    {children}    
    )    }           // ตรงนี้ใช้บอกว่าจะให้ Append เข้าไปที่ไหน    // จากตัวอย่างนี้ ผมจะใช้ append เข้าไปใน body เลย    , document.body)   }      export default Modal 

CSS สำหรับแต่ง Modal

ต้องบอกก่อนนะครับ ว่า CSS ชุดนี้ ไม่ได้รวมตัว Content ของ modal นะครับ เพราะผมทำให้มัน free เลย ไม่จำกัดว่า content ต้องเป็น card หรืออะไร ค่อยแต่งเอาทีหลัง และ CSS ผมจะใช้เป็นคำสั่งจาก tailwind นะครับ

เพื่อนๆ สามารถแต่งเองได้ตามสะดวกเลยครับ บทความนี้เป็นแค่ Guide เท่านั้น

.modal { @apply w-full h-full min-h-full fixed top-0 left-0 z-[100] p-4 flex items-center justify-center }  
.modal > .modal-backdrop { @apply w-full h-full bg-black/40 backdrop-blur-sm fixed top-0 left-0 z-[101] cursor-pointer }  
.modal > .modal-close-button { @apply absolute top-0 right-0 px-2 text-white text-4xl font-bold z-[200] }  
.modal > .modal-wrapper { @apply w-full h-fit max-w-screen-sm max-h-full overflow-y-scroll overflow-x-hidden relative top-0 left-0 z-[102] rounded-lg }  
.modal > .modal-wrapper > .modal-content { @apply w-full h-auto rounded-lg }  
.modal > .modal-wrapper > .modal-content > * { @apply break-words } 

ลองเรียกใช้

เราสามารถเรียกใช้ Modal จากหน้าไหนก็ได้ครับ เหมือนเราใช้ Framework UI ของเจ้าดังๆ เลย ติดแค่เสียเวลามาแต่ง แต่อิสระและมีความเป็นตัวเองมากๆ ครับ

import Modal from "@/components/Modal"  

export default function SomePage()  
{  
 const languages = [  
 { name: "ไทย", lang: "th" },  
 { name: "English", lang: "en" },  
 ]  
 return (    
Hello Bro !  
เลือกภาษา  
    {languages.map(language => (
{language.name}  

 )  
 }  

 )  
 }  


 )  
}  

Готово!!!

Коли ми відкриємо Inspector, то побачимо, що наш елемент Modal буде доданий в найнижчу частину body.

pic

Приклад, коли Modal був доданий до Body

Легко, так? Тепер ми можемо продовжити використовувати це для інших задач.

Якщо в статті є якісь помилки, вибачте за це.

Додаткові документи про createPortal:

https://react.dev/reference/react-dom/createPortal

Перекладено з: ใช้ ReactDOM createPortal สร้าง Component เช่น Modalในแบบของตัวเอง

Leave a Reply

Your email address will not be published. Required fields are marked *