Next.js Discord

Discord Forum

Modals with history in AppRouter

Unanswered
Violet-green Swallow posted this in #help-forum
Open in Discord
Violet-green SwallowOP
Any idea how correct implement modals with history??
My attempt: useModal (hook)

const modalId = searchParams.get(QUERY_PARAMS.Modal) || "";
useEffect(() => {
if (modalId === "") {
_close();
}
if (modalId === uuid) {
_open();
}
return () => {
_close();
}
}, [modalId])
but mby nextjs has something better for this.
I ran into an double navigation when I try change URL after close modal.
Any idea??

31 Replies

Violet-green SwallowOP
and using this hook is like:
const commentsModal = useModal({
id: "idModal",
type: ModalTypeEnum.COMMENTS,
render: (close) => {
return <CommentsDialog
onClose={close}
onSubmit={() => {
router.push("/homePage");
}}
/>
}
})

commentsModal.open();
Violet-green SwallowOP
I know about it but I want open different modals everywhere in my app. I mean i want confirm dialogs, submit dialogs etc etc...Dialogs by parallel route is for pages in dialogs and it works separately, its not my case. Do u understand?
@Violet-green Swallow I know about it but I want open different modals everywhere in my app. I mean i want confirm dialogs, submit dialogs etc etc...Dialogs by parallel route is for pages in dialogs and it works separately, its not my case. Do u understand?
parallel routes are for pages, yes. And intercepting routes allows you to load a route from another part of your application within the current layout.

So that should be excatly what you want, when you really need history.

When making confirm dialogs I like to have them clientside handled. Because: who needs history for confirm dialogs? I don't and because of that I wouldn't use the combination of intercepting routes and parallel routes just to have it in history
Violet-green SwallowOP
Understand but how can I send data from and to these dialogs?? bcs I need send data depend on context to dialog and after submit post data to place where I open the dialog...
@Violet-green Swallow Understand but how can I send data from and to these dialogs?? bcs I need send data depend on context to dialog and after submit post data to place where I open the dialog...
normally the dialog itself is just a wrapper and the dialog has some trigger. When the user clicks the trigger, the dialog content will be loaded. The dialog content will also be portaled to the body, so it's a layer over everything else. Like that it can be filled with data (where the trigger is) and also the actions in the dialog content can be filled with data from the trigger.

This could be one example:
const data = {...}

<Dialog>
  <DialogTrigger>Open</DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Are you absolutely sure to delete: {data.title}?</DialogTitle>
      <DialogDescription>
        This action cannot be undone. This will permanently delete your account
        and remove your data from our servers.
      </DialogDescription>
    </DialogHeader>
    <Button onClick={() => delete(data.id)}>Yes, I am sure</Button>
  </DialogContent>
</Dialog>
Violet-green SwallowOP
but how pass data to this dialog? I mean if this is parallel route in diffrent folder...how I access to data and how can I call callback after close dialog?
As you can see: both get the params and both get the current data. Like that both will have the same data and can do stuff depending on the data.
You can also see, that it is a lot more complicated then just doing it via clientside. And it's ok to do stuff clientside.
Violet-green SwallowOP
But in my case I want pass complexity data like user object.
@Violet-green Swallow But in my case I want pass complexity data like user object.
yea, the "photo", that you see in my example can be your "user"-object. It's a variable, so you can pass everything in it
Violet-green SwallowOP
but its special for modal with user....so If I want many dialogs with history I need many folders ??? Or can I use one folder for all history modals (generic modal)???
@Violet-green Swallow but its special for modal with user....so If I want many dialogs with history I need many folders ??? Or can I use one folder for all history modals (generic modal)???
you would need many intercepting routes, yes and also you need many slots for the specific path that you are on
Violet-green SwallowOP
bcs in my hook for modals is implemented that if I am on mobile device all modals has history. Bcs all my modals on mobile are fullscreen and lot of peaople try click back button when modal is open and they expect close dialog not redirect to previous page-...thats why I need this in one hook.
Violet-green SwallowOP
This is my hook which manage all modals:

export const useModal = <T = undefined>(settings: IUseModal<T>) : IUseModalResult<T> => {
const {id, render, options, type} = settings;
const uuid = createId(type, id);
const isMobile = useIsMobile();
const useHistory = options?.useHistory isMobile;
const isOpenRef = useRef(false);
const lastDataRef = useRef<T | undefined>(undefined);
const router = useBean(Router);
const modalManager = useBean(ModalManager);
const searchParams = useSearchParams();
const modalId = searchParams.get(QUERY_PARAMS.Modal)
"";

const _close = () => {
if (isOpenRef.current) {
isOpenRef.current = false;
modalManager.close();
}
}

const _open = (data?: T) => {
if (!isOpenRef.current) {
isOpenRef.current = true;
modalManager.open(() => render(() => {
useHistory ? router.back() : _close();
}, data), options);
}
}

useEffect(() => {
if (useHistory) {
if (modalId === "") {
_close();
}
if (modalId === uuid) {
_open(lastDataRef.current as T);
}
}
return () => {
_close();
}
}, [modalId])

return {
open: (data?: T) => {
lastDataRef.current = data;
if (useHistory) {
return router.addQueryParamAndPushUrl(QUERY_PARAMS.Modal, uuid, {scroll: false});
} else {
_open(data);
}
},
close: () => {
_close();
}
}
}
and usage:
const commentsModal = useModal({
id: "TripDetailSocialBarCommentsModal",
type: ModalTypeEnum.COMMENTS,
render: (close) => {
return <CommentsDialog
commentsStore={commentsStore}
onClose={close}
/>
}
})
pls can you tell me your opinion??
Violet-green SwallowOP
what exactly? πŸ™‚
@Violet-green Swallow what exactly? πŸ™‚
all of it πŸ™‚
I personally prefer simple and easy to use components instead of long and cofusing ones. That's a personal opinion. So don't feel offended πŸ‘
Violet-green SwallowOP
Its ok I dont πŸ™‚ .... just want talk about how would you solve this problem with history modals...
Violet-green SwallowOP
As you say, if I need only 2 types of modals (history, noHistory)...yes I can create two types of hooks...but on mobile I need all modals with history so thats why I created this hook
@Violet-green Swallow Its ok I dont πŸ™‚ .... just want talk about how would you solve this problem with history modals...
Yea, as said: I wouldn't use history modal for confirmation dialogs. I guess I can't help you more
Violet-green SwallowOP
not just confirm, picking someting etc etc...and only on mobile
@Violet-green Swallow not just confirm, picking someting etc etc...and only on mobile
I would still use a client modal most of the time
Violet-green SwallowOP
I consult it with my UX expert and he said that mobile modals should push history ... bcs modern website want to be like mobile apps...
@Violet-green Swallow I consult it with my UX expert and he said that mobile modals should push history ... bcs modern website want to be like mobile apps...
When I am on a website an there is an open modal I would never think of pressing the back button or swiping back. Maybe I am the one and only who thinks so, but I think there are many others that think the same.

Yes in a mobile app, I think that would happen, that I would swipe back or press the back button to get back and then I also know, that I am inside an app and because of that I can get back.

When building my own (clientside modals) the back functionality is already disabled.
That's what others say about it: https://nextjs-forum.com/post/1275882365222260808#message-1276217467152105533
Violet-green SwallowOP
Mby only my UX designer want this back button behaviour on mobile πŸ˜„
but yes i understand u πŸ™‚ thx for discussion πŸ™‚