<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مرتضی حسینی</title>
        <link>https://virgool.io/feed/@mortezahosseini901</link>
        <description>یه برنامه نویس مشتاق یادگیری</description>
        <language>fa</language>
        <pubDate>2026-06-19 03:56:47</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/536732/avatar/WLo0mP.jpeg?height=120&amp;width=120</url>
            <title>مرتضی حسینی</title>
            <link>https://virgool.io/@mortezahosseini901</link>
        </image>

                    <item>
                <title>نحوه ساختن مدال در ریکت فانکشنال کامپوننت و کلاس کامپوننت با قابلیت دکمه بازگشت مرورگر (create modal in functional and class component with back handler )</title>
                <link>https://virgool.io/@mortezahosseini901/%D9%86%D8%AD%D9%88%D9%87-%D8%B3%D8%A7%D8%AE%D8%AA%D9%86-%D9%85%D8%AF%D8%A7%D9%84-%D8%AF%D8%B1-%D8%B1%DB%8C%DA%A9%D8%AA-%D9%81%D8%A7%D9%86%DA%A9%D8%B4%D9%86%D8%A7%D9%84-%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA-%D9%88-%DA%A9%D9%84%D8%A7%D8%B3-%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA-%D8%A8%D8%A7-%D9%82%D8%A7%D8%A8%D9%84%DB%8C%D8%AA-%D8%AF%DA%A9%D9%85%D9%87-%D8%A8%D8%A7%D8%B2%DA%AF%D8%B4%D8%AA-%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1-create-modal-in-functional-and-class-component-with-back-handler-xety899yz5md</link>
                <description>چند وقت پیش من و همکارم که رو یه پروژه ای کار میکردیم، خیلی گشتیم تو منابع فارسی و انگلیسی و هیچ جا مقاله درست حسابی برای اینکه چجوری میشه وقتی یه popover یا modal باز هست، با زدن دکمه back مرورگر، مدال بسته بشه. ولی خب مقاله مناسبی پیدا نشد. برای همین شروع کردیم به ساختن یه کامپوننت مدال کاستومایز شده و وظیفه خودمون دونستیم تا این مطلب رو با شما به اشتراک بگذاریم که حداقل به دولوپرهای بعد از خودمون کمک کرده باشیم ?❤️. تمرکز این مقاله بر این هست که وقتی مدال باز هست، با کلیک یوزر بر دکمه بازگشت مرورگر، مدال بسته بشه و توی همون پیج بمونیم. یعنی عملا یک backHandler برای دکمه بازگشت مرورگر بسازیم. در زیر میتونید دمو رو برای هر دو حالت functioinal و class کامپوننت ببینید. قراره خوش بگذرونیم ??demo for: functioanl componentdemo for: soon...لازم به ذکر هست که بنده در این مقاله و دمو از typescript, next.js استفاده کردم تا هر حالتی رو پوشش بدم. عزیزانی که از react استفاده میکنن به جای next، کافی هست که از react-router-dom به جای next-router استفاده کنند.برای ساختن مدال از یه پلاگین خیلی خوب توی npm استفاده میکنیم تا بتونیم مدال خودمون رو درست کنیم. اسم پلاگین هست react-responsive-modal که برای نصبش کافیه کد زیر رو در cmd یا terminal خودتون ران کنید:yarn add react-responsive-modalحالا که ما این پکیج رو نصب کردیم، میتونیم اون رو در فایل package.json اپلیکیشن ریکت خودتمون ببینیم، پس بریم سراغ اینکه یه کامپوننت مدال کاستومایز برای خودمون بسازیم. نحوه استفاده از کامپوننت های react-responsive-modal در این لینک کامل توضیح داده شده. در زیر به صورت مجزا برای فانکشنال کامپوننت و کلاس کامپوننت ریکت نحوه استفاده از کامپوونت های react-responsive-modal رو آوردیم. لازم به ذکر هست که ما به جای react-router از next-router استفاده کردیم. تفاوت زیادی در نحوه تغییر روت وجود ندارد.Functional Component//  custom-modal.tsx

import React, { FC, useState, ReactNode } from &#039;react&#039;;
import { Modal } from &#039;react-responsive-modal&#039;;
import &amp;quotreact-responsive-modal/styles.css&amp;quot

interface IProps {
   name: string
   hideModal: () =&gt; void
   visible: boolean
   children: ReactNode
}

const CustomModal: FC&lt;IProps&gt; = ({name, hideModal, visible, children}) =&gt; {
    const [showModal, setShowModal] = useState&lt;boolean&gt;(visible || false);
    
    const open = () =&gt; setShowModal(true);
    const close = () =&gt; setShowModal(false);

    return (
        &lt;Modal 
            open={showModal}
            ={close}
            onOverlayClick={close }
            closeOnEsc
        &gt;
            {children}
        &lt;/Modal &gt;
    )
} 

export default CustomModalClass Component// custom-modal.tsx

import React , { Component, ReactNode } from &#039;react&#039;;
import { Modal } from &#039;react-responsive-modal&#039;;
import &amp;quotreact-responsive-modal/styles.css&amp;quot

interface IProps {
    name: string
    hideModal: () =&gt; void
    visible: boolean
    children: ReactNode
}
interface IState {
    showModal: boolean
}

class CustomModal extends Component&lt;IProps, IState&gt; {
    constructor(props: IProps) {
        super(props)
        this.state = {showModal: this.props.visible || false}
    };

    close () {
        this.setState({
            showModal: false
        })
    }

    render () {
        return (
           &lt;Modal
              open={this.state.showModal}
             ={this.close}
             onOverlayClick={this.close }
             closeOnEsc
         &gt;
             {this.props.children}
         &lt;/Modal &gt;
        )
    };
}

export default CustomModal ;حالا که کامپوننت custom-modal رو ساختیم، میتونیم توی هر کامپوننتی از اون استفاده کنیم. کافیه با هر ایونتی جاوااسکریپتی که مد نظرمون هست (مثلا کلیک) به کامپوونت custom-modal پراپرتی visiblie = true پاس بدیم. الان دیگه میتونیم بریم سراغ اینکه برای کامپوننت مدالمون backHandler ست کنیم. چجوری؟ ??وقتی مدال باز هست، با کلیک روی دکمه بازگشت مرورگر، باید مدال باز بشه. راهکار چی هست حالا؟ ?? کد زیر رو ببینید که چطور ما custom-modal رو ویرایش کردیم.Functional Component// custom-modal.tsx

import React , { FC, memo, useEffect, useState, ReactNode } from &#039;react&#039;; 
import { Modal } from &#039;react-responsive-modal&#039;; 
import &amp;quotreact-responsive-modal/styles.css&amp;quot
import { useRouter } from &#039;next/router&#039;;

interface IProps {
    name: string
    hideModal: () =&gt; void
    visible: boolean
    children: ReactNode
}

const CustomModal: FC&lt;IProps&gt; = ({name, hideModal, visible, children}) =&gt; {     
    const [showModal, setShowModal] = useState&lt;boolean&gt;(visible || false);
    const router = useRouter();
    const hasHash = router.asPath.includes(&#039;#&#039;)

    const open = () =&gt; {
        if (!hasHash) {
            router.push({
                pathname: router.pathname,
                query: { ...router.query },
                hash: name + &#039;&#039;
            }, undefined, { scroll: false })
        }
        setShowModal(true);
    }

    const close = () =&gt; {
        hideModal();
        setShowModal(false);
        if (showModal) {
            router.back()
        }
    }
    const clickOutSide = () =&gt; {
        hideModal();
        setShowModal(false);
    }

    useEffect(() =&gt; {
        visible &amp;&amp; open()
    }, [visible])
    useEffect(() =&gt; {
        if (!hasHash &amp;&amp; showModal) hideModal
(), setShowModal(false)
    }, [hasHash]);

return ( 
        &lt;Modal
              open={showModal}
             ={close}
             onOverlayClick={close }
             closeOnEsc
         &gt;
             {children}
         &lt;/Modal &gt;
  ) 
}

export default memo(CustomModal);
Class Component// custom-modal

import React , { Component, ReactNode } from &#039;react&#039;;
 import { Modal } from &#039;react-responsive-modal&#039;; 
import &amp;quotreact-responsive-modal/styles.css&amp;quot

interface IProps {
     name: string
     hideModal: () =&gt; void
     visible: boolean
     children: ReactNode } 
interface IState {
     showModal: boolean 
}

class CustomModal extends Component&lt;IProps, IState&gt; {
     constructor(props: IProps) {
         super(props)
         this.state = {showModal: this.props.visible || false}
     };

     close () {
         this.setState({
             showModal: false
         })
     }
      render () {
         return (
            &lt;Modal
               open={this.state.showModal}
              ={this.close}
              onOverlayClick={this.close }
              closeOnEsc
          &gt;
              {this.props.children}
          &lt;/Modal &gt;
         )
     };
}


export default CustomModal;چی شد؟ ??وقتی که مدال باز باشه، ما یه modalName# به انتهای روتمون اضافه میکنیم. وقتی هم که مدال باید بسته بشه یا یوزر دکمه بازگشت مرورگر رو بزنه، ما # رو بر میداریم. خیلی راحت عملا داریم روتر رو تغییر میدیم و با باز و بسته شدن مدال این روت آپدیت میشه. حالا یک سوال اگر مدال باز باشه و یوزر صفحه رو رفرش کنه، چی میشه؟ باید بگم که با رفرش کردن صفحه روتر با # به یوزر نشون داده میشه. وقتی یوزر روی دکمه باز کردن مدال کلیک کرد، # همون هست ولی خب مدال رو باز هم میبینید. یعنی مشکلی ایجاد نمیکنه.اگر نیاز داشتیم میتونیم با رفرش، به صورت دیفالت روت را بدون # نشون بدیم که این قسمت به عهده خود شما ??. حالا چرا با # مگه با query string نمیشد هندل کرد؟ بله با کوئری استرینگ هم میشه هندل کرد ولی روتر ریکت و نکست دیفالتش اینه وقتی که کوئری استرینگ و پارامتر های روت تغییر میکنه، اسکرول میکنه به بالای صفحه. پس ما درد سر تغییر دیفالت روتر رو به جون نخریدیم و از # استفاده کردیم.با تشکر از همکاری دوست خوبم نیلوفر صادقی https://virgool.io/@niloofar_sadeghi </description>
                <category>مرتضی حسینی</category>
                <author>مرتضی حسینی</author>
                <pubDate>Wed, 18 Aug 2021 10:14:27 +0430</pubDate>
            </item>
            </channel>
</rss>