فارسی

راهنمای جامع پورتال‌های React، شامل موارد استفاده، پیاده‌سازی، مزایا و بهترین شیوه‌ها برای رندر محتوا خارج از سلسله‌مراتب استاندارد کامپوننت.

پورتال‌های React: رندر کردن محتوا خارج از درخت کامپوننت

پورتال‌های React مکانیزم قدرتمندی برای رندر کردن کامپوننت‌های فرزند در یک گره DOM فراهم می‌کنند که خارج از سلسله‌مراتب DOM کامپوننت والد قرار دارد. این تکنیک در سناریوهای مختلفی مانند مودال‌ها، تولتیپ‌ها (tooltips) و موقعیت‌هایی که نیاز به کنترل دقیق بر روی موقعیت و ترتیب قرارگیری (stacking order) عناصر در صفحه دارید، بسیار ارزشمند است.

پورتال‌های React چه هستند؟

در یک برنامه کاربردی React معمولی، کامپوننت‌ها در یک ساختار سلسله‌مراتبی سخت رندر می‌شوند. کامپوننت والد شامل کامپوننت‌های فرزند است و به همین ترتیب ادامه می‌یابد. با این حال، گاهی اوقات شما نیاز دارید از این ساختار خارج شوید. اینجاست که پورتال‌های React وارد می‌شوند. یک پورتال به شما اجازه می‌دهد محتوای یک کامپوننت را در بخش دیگری از DOM رندر کنید، حتی اگر آن بخش از نوادگان مستقیم کامپوننت در درخت React نباشد.

تصور کنید یک کامپوننت مودال دارید که باید در بالاترین سطح برنامه شما نمایش داده شود، صرف نظر از اینکه در کجای درخت کامپوننت رندر شده است. بدون پورتال‌ها، ممکن است سعی کنید با استفاده از موقعیت‌دهی مطلق (absolute positioning) و z-index به این هدف برسید، که می‌تواند منجر به مشکلات پیچیده استایل‌دهی و تداخل‌های احتمالی شود. با پورتال‌ها، شما می‌توانید مستقیماً محتوای مودال را در یک گره DOM مشخص، مانند یک عنصر اختصاصی "modal-root"، رندر کنید و اطمینان حاصل کنید که همیشه در سطح صحیح رندر می‌شود.

چرا از پورتال‌های React استفاده کنیم؟

پورتال‌های React چندین چالش رایج در توسعه وب را برطرف می‌کنند:

چگونه پورتال‌های React را پیاده‌سازی کنیم

استفاده از پورتال‌های React سرراست است. در اینجا یک راهنمای گام به گام آورده شده است:

  1. ایجاد یک گره DOM: ابتدا، یک گره DOM ایجاد کنید که می‌خواهید محتوای پورتال را در آن رندر کنید. این کار معمولاً در فایل `index.html` شما انجام می‌شود. به عنوان مثال:
    <div id="modal-root"></div>
  2. استفاده از `ReactDOM.createPortal()`: در کامپوننت React خود، از متد `ReactDOM.createPortal()` برای رندر کردن محتوا در گره DOM ایجاد شده استفاده کنید. این متد دو آرگومان می‌گیرد: گره React (محتوایی که می‌خواهید رندر کنید) و گره DOM که می‌خواهید آن را در آنجا رندر کنید.
    import ReactDOM from 'react-dom';
    
    function MyComponent() {
      return ReactDOM.createPortal(
        <div>این محتوا در modal-root رندر می‌شود!</div>,
        document.getElementById('modal-root')
      );
    }
    
    export default MyComponent;
  3. رندر کردن کامپوننت: کامپوننتی که حاوی پورتال است را مانند هر کامپوننت React دیگری رندر کنید.
    function App() {
      return (
        <div>
          <h1>My App</h1>
          <MyComponent />
        </div>
      );
    }
    
    export default App;

در این مثال، محتوای داخل `MyComponent` در داخل عنصر `modal-root` رندر خواهد شد، حتی اگر `MyComponent` در داخل کامپوننت `App` رندر شده باشد.

مثال: ایجاد یک کامپوننت مودال با پورتال‌های React

بیایید یک کامپوننت مودال کامل با استفاده از پورتال‌های React ایجاد کنیم. این مثال شامل استایل‌دهی اولیه و قابلیت باز و بسته کردن مودال است.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

const modalRoot = document.getElementById('modal-root');

function Modal({ children, onClose }) {
  const [isOpen, setIsOpen] = useState(true);

  const handleClose = () => {
    setIsOpen(false);
    onClose();
  };

  if (!isOpen) return null;

  return ReactDOM.createPortal(
    <div className="modal-overlay">
      <div className="modal">
        <div className="modal-content">
          {children}
        </div>
        <button onClick={handleClose}>بستن</button>
      </div>
    </div>,
    modalRoot
  );
}

function App() {
  const [showModal, setShowModal] = useState(false);

  const handleOpenModal = () => {
    setShowModal(true);
  };

  const handleCloseModal = () => {
    setShowModal(false);
  };

  return (
    <div>
      <h1>برنامه من</h1>
      <button onClick={handleOpenModal}>باز کردن مودال</button>
      {showModal && (
        <Modal onClose={handleCloseModal}>
          <h2>محتوای مودال</h2>
          <p>این محتوای مودال است.</p>
        </Modal>
      )}
    </div>
  );
}

export default App;

در این مثال:

شما همچنین باید مقداری استایل CSS به کلاس‌های `modal-overlay` و `modal` اضافه کنید تا مودال به درستی روی صفحه قرار گیرد. به عنوان مثال:

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
}

.modal-content {
  margin-bottom: 10px;
}

مدیریت رویدادها (Events) با پورتال‌ها

یک نکته مهم هنگام استفاده از پورتال‌ها، نحوه مدیریت رویدادها است. انتشار رویداد (Event bubbling) با پورتال‌ها متفاوت از کامپوننت‌های استاندارد React عمل می‌کند.

هنگامی که یک رویداد در داخل یک پورتال رخ می‌دهد، طبق معمول در درخت DOM به سمت بالا منتشر می‌شود. با این حال، سیستم رویداد React با پورتال به عنوان یک گره معمولی React رفتار می‌کند، به این معنی که رویدادها همچنین در درخت کامپوننت React که حاوی پورتال است به سمت بالا منتشر می‌شوند.

این موضوع گاهی اوقات می‌تواند منجر به رفتار غیرمنتظره شود اگر مراقب نباشید. به عنوان مثال، اگر یک کنترل‌کننده رویداد (event handler) روی یک کامپوننت والد داشته باشید که فقط باید توسط رویدادهای داخل آن کامپوننت فعال شود، ممکن است توسط رویدادهای داخل پورتال نیز فعال شود.

برای جلوگیری از این مشکلات، می‌توانید از متد `stopPropagation()` روی شیء رویداد استفاده کنید تا از انتشار بیشتر رویداد به سمت بالا جلوگیری کنید. به طور جایگزین، می‌توانید از رویدادهای مصنوعی React و رندر شرطی برای کنترل زمان فعال شدن کنترل‌کننده‌های رویداد استفاده کنید.

در اینجا مثالی از استفاده از `stopPropagation()` برای جلوگیری از انتشار رویداد به کامپوننت والد آورده شده است:

function MyComponent() {
  const handleClick = (event) => {
    event.stopPropagation();
    console.log('داخل پورتال کلیک شد!');
  };

  return ReactDOM.createPortal(
    <div onClick={handleClick}>این محتوا در پورتال رندر شده است.</div>,
    document.getElementById('portal-root')
  );
}

در این مثال، کلیک کردن روی محتوای داخل پورتال تابع `handleClick` را فعال می‌کند، اما رویداد به هیچ کامپوننت والدی منتشر نخواهد شد.

بهترین شیوه‌ها برای استفاده از پورتال‌های React

در اینجا چند بهترین شیوه برای به خاطر سپردن هنگام کار با پورتال‌های React آورده شده است:

جایگزین‌های پورتال‌های React

در حالی که پورتال‌های React ابزار قدرتمندی هستند، رویکردهای جایگزینی وجود دارد که می‌توانید برای رسیدن به نتایج مشابه از آنها استفاده کنید. برخی از جایگزین‌های رایج عبارتند از:

انتخاب رویکرد مورد استفاده به نیازمندی‌های خاص برنامه شما و پیچیدگی عناصر UI که در تلاش برای ایجاد آن هستید بستگی دارد. پورتال‌ها به طور کلی بهترین گزینه هستند زمانی که به کنترل دقیق بر موقعیت و ترتیب قرارگیری عناصر نیاز دارید و می‌خواهید از تداخل‌های CSS جلوگیری کنید.

ملاحظات جهانی

هنگام توسعه برنامه‌ها برای مخاطبان جهانی، در نظر گرفتن عواملی مانند بومی‌سازی، دسترسی‌پذیری و تفاوت‌های فرهنگی ضروری است. پورتال‌های React می‌توانند در پرداختن به این ملاحظات نقش داشته باشند:

با در نظر گرفتن این ملاحظات جهانی، می‌توانید برنامه‌های کاربردی فراگیرتر و کاربرپسندتری برای مخاطبان متنوع ایجاد کنید.

نتیجه‌گیری

پورتال‌های React ابزاری قدرتمند و همه‌کاره برای رندر کردن محتوا خارج از درخت استاندارد کامپوننت هستند. آنها راه‌حلی تمیز و زیبا برای الگوهای رایج UI مانند مودال‌ها، تولتیپ‌ها و پاپ‌اورها ارائه می‌دهند. با درک نحوه کار پورتال‌ها و پیروی از بهترین شیوه‌ها، می‌توانید برنامه‌های React انعطاف‌پذیرتر، قابل نگهداری‌تر و در دسترس‌تری ایجاد کنید.

پورتال‌ها را در پروژه‌های خود آزمایش کنید و راه‌های بسیاری را که می‌توانند گردش کار توسعه UI شما را ساده کنند، کشف کنید. به یاد داشته باشید که هنگام استفاده از پورتال‌ها در برنامه‌های تولیدی، مدیریت رویدادها، دسترسی‌پذیری و ملاحظات جهانی را در نظر بگیرید.

با تسلط بر پورتال‌های React، می‌توانید مهارت‌های React خود را به سطح بالاتری برسانید و برنامه‌های وب پیچیده‌تر و کاربرپسندتری برای مخاطبان جهانی بسازید.