I created a Modal as compound component that manages all its state itself. Now i’m trying to open modal and render PostDetails component inside it. Modal getting open and component rendering as well but url not getting updated.
if i go without modal, url updated. but i want to open postDetails component inside modal and at the same time url should also updated. because i’ll use params to fetch post details later.
Modal component ::
import { createContext, useState, useContext, cloneElement } from "react";
import { createPortal } from "react-dom";
import { RiCloseLargeLine } from "react-icons/ri";
import PropTypes from 'prop-types'
const ModalContext = createContext();
const ModalProvider = ({ children }) => {
const [openName, setOpenName] = useState("");
const close = () => setOpenName("");
const open = (name) => setOpenName(name);
return (
<ModalContext.Provider value={{ openName, close, open }}>
{children}
</ModalContext.Provider>
);
};
const useModalContext = () => useContext(ModalContext);
const Modal = ({ children }) => {
return <>{children}</>;
};
const ModalOverlay = ({ children, isOpen, onClose }) => {
if (!isOpen) return null;
return <div className="fixed inset-0 z-50 flex items-center justify-center">
<div
className="fixed inset-0 backdrop-blur-[2px]"
onClick={onClose}
></div>
<div className="relative z-50 rounded-lg shadow-lg ">
{children}
</div>
<button
className="absolute md:top-5 top-3 right-3 md:right-5 p-1 md:p-1.5 "
onClick={onClose}
>
<RiCloseLargeLine className="w-7 h-7 " />
</button>
</div>
};
const Open = ({ children, opens: opensWindowName }) => {
const { open } = useModalContext();
return cloneElement(children, { onClick: () => open(opensWindowName) });
};
const Window = ({ children, name }) => {
const { openName, close } = useModalContext();
if (name !== openName) return null;
return createPortal(
<ModalOverlay isOpen={true} onClose={close}>
{cloneElement(children, { closeModal: close })}
</ModalOverlay>,
document.body
);
};
Modal.Open = Open;
Modal.Window = Window;
ModalContext.propTypes={
children: PropTypes.element
}
ModalProvider.propTypes={
children: PropTypes.element
}
Modal.propTypes={
children: PropTypes.element
}
ModalOverlay.propTypes={
children: PropTypes.element,
isOpen: PropTypes.bool,
onClose: PropTypes.func
}
Window.propTypes={
children: PropTypes.element,
name: PropTypes.string
}
export { ModalProvider, useModalContext, Modal };
Below is list of posts. and if i click any of them, url should be update and post should be open inside the modal. and if user click anywhere except the post, modal will get close and user should got back to previous state ( post list page ).
import { useNavigate, useOutletContext } from "react-router-dom";
import { ModalProvider, Modal } from "../../ui/Modal";
import PostDetails from "./PostDetails";
const UserPosts = () => {
const [{ ownPosts }] = useOutletContext();
const navigate = useNavigate();
return (
<ModalProvider>
<ul className="grid gap-2 py-2 lg:grid-cols-3 xl:grid-cols-4 md:grid-cols-2 max-sm:gap-y-2">
{ownPosts &&
ownPosts?.map((post) => (
<figure
key={post?._id}
className=" rounded max-h-[340px] h-[340px]"
>
<Modal.Open opens="post-details-open">
<img
onClick={() => navigate(`/post/${post?._id}`)}
src={post?.mediaUrl}
alt="post image"
className="object-cover w-full h-full rounded"
/>
</Modal.Open>
</figure>
))}
</ul>
<Modal.Window name="post-details-open">
<PostDetails />
</Modal.Window>
</ModalProvider>
);
};
export default UserPosts;
i tried to go with component as well but result is same as with navigate.
please guide for it, how i can achieve it.
thanks