Volunteer Profile Page Modal
Unanswered
Brown bear posted this in #help-forum
Brown bearOP
I'm using the @modal to display a modal profile, and when I try to navigate to the route, I get an error:
Why is that? And how can I go about fixing it?
app-index.js:31 The above error occurred in the <Router> component:
at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:150:11)
at ErrorBoundaryHandler (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:77:9)
at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:102:11)
at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:396:13)
at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:162:11)
at RSCComponent
at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:178:11)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundaryHandler.Why is that? And how can I go about fixing it?
110 Replies
Brown bearOP
Brown bearOP
@DirtyCajunRice | AppDir Sorry to ping you, but nobody has been able to help solve this for a while now. Could you help solve this? Thanks.
probably because you dont have a default.ts
@DirtyCajunRice | AppDir probably because you dont have a default.ts
Brown bearOP
where should I put that?
@Brown bear where should I put that?
same place in any @ folder as a page.tsx
its just a guess tho
@DirtyCajunRice | AppDir same place in any @ folder as a page.tsx
Brown bearOP
Am I doing it correctly?
wat. no
you need a default.tsx
in the same folder as page.tsx
anywhere there is a page.tsx
in the @ folder
@DirtyCajunRice | AppDir in the @ folder
Brown bearOP
like this?
Brown bearOP
the error still occours
@DirtyCajunRice | AppDir ye
Brown bearOP
app-index.js:31 The above error occurred in the <Router> component:
at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:150:11)
at ErrorBoundaryHandler (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:77:9)
at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:102:11)
at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:396:13)
at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:162:11)
at RSCComponent
at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:178:11)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundaryHandler.
at Router (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:150:11)
at ErrorBoundaryHandler (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:77:9)
at ErrorBoundary (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/error-boundary.js:102:11)
at AppRouter (webpack-internal:///(app-client)/./node_modules/next/dist/client/components/app-router.js:396:13)
at ServerRoot (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:162:11)
at RSCComponent
at Root (webpack-internal:///(app-client)/./node_modules/next/dist/client/app-index.js:178:11)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundaryHandler.
then you have an error in your modal
show your modal code
and paste the path you are going to
Brown bearOP
'use client'
function VolunteerProfileDialog({ params: { oid } }: { params: { oid: string } }) {
const { user, orgId } = useData();
const [token, setToken] = useState<string | null>(null);
const [volunteer, setVolunteer] = useState<VolunteerBaseWithId | null >(null);
console.log("rendering VolunteerProfileDialog")
const volunteerId = oid;
useEffect(() => {
const fetchToken = async () => {
if (user) {
const fetchedToken = await getIdToken(user);
setToken(fetchedToken);
}
};
fetchToken();
}, [user]);
const {
isLoading,
error,
} = useQuery(['volunteer', volunteerId], () => fetchVolunteer(volunteerId, orgId as string, token as string), {
enabled: !!token,
onSuccess: data => {
// Do something with the data once the request is successful
setVolunteer(data.volunteer);
},
});
if (isLoading) return <Loader />;
if (error) return <ErrorScreen error={(error as Error).message} />;
if (!volunteer) return <ErrorScreen error="Volunteer not found" />;
return (
<Dialog>
<DialogContent>
<DialogHeader>
<DialogTitle>Volunteer Profile</DialogTitle>
</DialogHeader>
<DialogDescription>
<Tabs defaultValue="profile">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="details">Details</TabsTrigger>
</TabsList>
<TabsContent value="profile">
<Label>Hi:</Label>
</TabsContent>
<TabsContent value="details">
<Label>Volunteer ID:</Label>
<Input value={volunteer.void} readOnly />
</TabsContent>
</Tabs>
</DialogDescription>
<DialogFooter>
<button onClick={() => console.log('Close dialog')}>Close</button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
export default VolunteerProfileDialogwait…
wheres your layout
Brown bearOP
its under the dashboard folder
so all pages have it
yes but @modal is under /dashboard/[org_slug] isnt it?
Brown bearOP
yep
show me layout
like the code
Brown bearOP
import React from 'react';
import Sidebar from './Sidebar';
import Topbar from './Topbar'
import { useAuth } from '@contexts/AuthProvider';
import { useData, DataProvider } from '@contexts/DataProvider';
import { usePathname } from 'next/navigation';
import { Toaster } from 'react-hot-toast';
import fetchAdminOrganization from '@get/fetchAdminOrganization';
export default function DashboardLayout({
children,
params: { org_slug },
}: {
children: React.ReactNode;
params: { org_slug: string };
}) {
console.log(org_slug); // This will log the value of org_name directly
return (
<section>
<DataProvider org_slug={org_slug}>
<div className="page-background flex flex-col">
<Topbar />
<Sidebar/>
<div className="flex-grow ml-64 mt-12 mr-4">{children}</div>
</div>
</DataProvider>
</section>
);
}yeah thats the problem
@foldername is a new prop
you have children and modal now
but you arent refrencing modal at all
Brown bearOP
how can I reference it then?
did you look at the docs on parallel routes?
it shows you
Brown bearOP
oh I see
In the docs when you go to the modals section it doesnt talk about that at all
only in the parallel routes modal section
yeah, i guess they assume you dont skip past parallel routes docs before going to a specific use case of them 😅
Brown bearOP
Oh actually just checked, it was under the intercepting routes section
thats why I did it like that
import React from 'react';
import Sidebar from './Sidebar';
import Topbar from './Topbar'
import { useAuth } from '@contexts/AuthProvider';
import { useData, DataProvider } from '@contexts/DataProvider';
import { usePathname } from 'next/navigation';
import { Toaster } from 'react-hot-toast';
import fetchAdminOrganization from '@get/fetchAdminOrganization';
export default function DashboardLayout({
children,
params: { org_slug },
modal,
}: {
children: React.ReactNode;
params: { org_slug: string };
modal: React.ReactNode;
}) {
console.log(org_slug); // This will log the value of org_name directly
return (
<section>
<DataProvider org_slug={org_slug}>
<div className="page-background flex flex-col">
<Topbar />
<Sidebar/>
<div className="flex-grow ml-64 mt-12 mr-4">
{children}
{modal}
</div>
</div>
</DataProvider>
</section>
);
}@DirtyCajunRice | AppDir yeah, i guess they assume you dont skip past parallel routes docs before going to a specific use case of them 😅
Brown bearOP
am I missing something? It still gives the error
@DirtyCajunRice | AppDir but you arent refrencing modal at all
Brown bearOP
Ok I changed the modal to match the proper path but it wont show as modal or give an error. Why is that?
you now. need to add a layout to volunteers
because your @ is in that folder now not dashboard
@DirtyCajunRice | AppDir because your @ is in that folder now not dashboard
Brown bearOP
import React from 'react';
export default function VolunteerLayout({
children,
modal,
}: {
children: React.ReactNode;
modal: React.ReactNode;
}) {
return (
<>
{children}
{modal}
</>
);
}I now get a 404 error.
you need oid
both give 404 now
Brown bearOP
org_slug
Brown bearOP
after I saved it did that
I just saved again, nothing changed
show me whats in [oid]
Brown bearOP
'use client'
import { useState, useEffect } from "react"
import { useQuery } from '@tanstack/react-query';
import { fetchVolunteer } from "@get/fetchVolunteers"
import { getIdToken } from 'firebase/auth';
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
import { useData } from '@contexts/DataProvider';
import Loader from '@components/Loader';
import ErrorScreen from '@components/ErrorScreen';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@components/ui/tabs';
import { Card, CardHeader, CardTitle, CardContent, CardDescription } from '@components/ui/card';
import { Input } from "@components/ui/input"
import { Label } from "@components/ui/label"
function VolunteerProfilePage({ params: { oid } }: { params: { oid: string } }) {
const {
isLoading,
error,
} = useQuery(['volunteer', volunteerId], () => fetchVolunteer(volunteerId, orgId as string, token as string), {
enabled: !!token,
onSuccess: data => {
// Do something with the data once the request is successful
setVolunteer(data.volunteer);
},
});
if (isLoading) return <Loader />;
if (error) return <ErrorScreen error={(error as Error).message} />;
if (!volunteer) return <ErrorScreen error="Volunteer not found" />;
return (
<div className="mt-9 ml-8 mr-8">
<Card>
<CardHeader>
<CardTitle>Volunteer Profile</CardTitle>
</CardHeader>
<CardContent>
<Tabs defaultValue="profile">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="details">Details</TabsTrigger>
</TabsList>
<TabsContent value="profile">
<CardDescription>
</CardDescription>
</TabsContent>
</Tabs>
</CardContent>
</Card>
</div>
);
}
export default VolunteerProfilePage'use client'
import { useState, useEffect } from "react"
import { useQuery } from '@tanstack/react-query';
import { fetchVolunteer } from "@get/fetchVolunteers"
import { getIdToken } from 'firebase/auth';
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
import { useData } from '@contexts/DataProvider';
import Loader from '@components/Loader';
import ErrorScreen from '@components/ErrorScreen';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@components/ui/tabs';
import { Input } from "@components/ui/input"
import { Label } from "@components/ui/label"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@components/ui/dialog"
function VolunteerProfileDialog({ params: { oid } }: { params: { oid: string } }) {
return (
<Dialog>
<DialogContent>
<DialogHeader>
<DialogTitle>Volunteer Profile</DialogTitle>
</DialogHeader>
<DialogDescription>
<Tabs defaultValue="profile">
<TabsList>
<TabsTrigger value="profile">Profile</TabsTrigger>
<TabsTrigger value="details">Details</TabsTrigger>
</TabsList>
<TabsContent value="profile">
</TabsContent>
</Tabs>
</DialogDescription>
<DialogFooter>
<button onClick={() => console.log('Close dialog')}>Close</button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
export default VolunteerProfileDialog@DirtyCajunRice | AppDir show me whats in [oid]
Brown bearOP
top is the [oid] page and bottom is modal
im so confused
it should work
stop the app
delete .next
start the app
if that doesn’t work its console.log time
Brown bearOP
ok I did it, and it works, except for the modal part
@DirtyCajunRice | AppDir if that doesn’t work its console.log time
Brown bearOP
it just goes directly to page
I put console logging statements on both and it says that they both render for some reason
i dont see anything telling the modal to open and close
@DirtyCajunRice | AppDir yeah it will render
Brown bearOP
for some reason, when I refresh the page, the modal appears, but when I am redirected, it renders the page not the modal. Why is that??
app-index.js:31 Warning: validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
at div
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:46:23)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:20:23)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
at Provider (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-context/dist/index.mjs:47:28)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-roving-focus/dist/index.mjs:69:38)
at eval (webpack-internal:///(app-
I also get this error
at div
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:46:23)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-slot/dist/index.mjs:20:23)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-primitive/dist/index.mjs:44:26)
at Provider (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-context/dist/index.mjs:47:28)
at eval (webpack-internal:///(app-client)/./node_modules/@radix-ui/react-roving-focus/dist/index.mjs:69:38)
at eval (webpack-internal:///(app-
I also get this error
this is why i said the other day that i dont think the modal is a good use case of parallel routes
even though its in the docs
Brown bearOP
so how can I make it so that the modal shows properly though
on redirect
why do you think you need parallel routes
lets start with that
Brown bearOP
to show a modal popup essentially
but also have a dedicated page to view profile too
my perception of modal page was easier way of doing modal
its not
its super misleading imo
Brown bearOP
oh
you should've told me that from the start lmao
hindsight 2020 haha
Brown bearOP
well my modal does fetch data and if I add it as a component, it will fetch data when it does not pop up
I only want it to fetch when it pops up
i tried REALLY hard to do it this way too. to fully grasp why the docs used it as an example. i came to the conclusion that it just simply is an example, but not one you should use in practice
and wrap its definition around the open check
Brown bearOP
ill try that
Brown bearOP
Have you done dialogs with tables?
I'm going crazy with this Shadcn table structure. I'm putting the Dialog wrapped around the edit volunteer button and when I open the actions, it console logs that it is rendered, but when I click edit volunteer, the dialog does not show. Am I doing this the right way? When I test the dialog wrapper around a normal button, it works as intended. Why is that?
I'm going crazy with this Shadcn table structure. I'm putting the Dialog wrapped around the edit volunteer button and when I open the actions, it console logs that it is rendered, but when I click edit volunteer, the dialog does not show. Am I doing this the right way? When I test the dialog wrapper around a normal button, it works as intended. Why is that?
<div className="mt-9 ml-8 mr-8">
<h2 className="mt-2 mb-2 text-3xl font-bold tracking-tight">Volunteers</h2>
<VolunteerDataTable columns={columns} data={volunteerData} />
</div> const columns: ColumnDef<VolunteerBaseWithId>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected()}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
{
id: "actions",
cell: ({ row }) => {
const volunteer = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open menu</span>
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<VolunteerProfilePopup volunteerId={volunteer.void}>
<button>
<DropdownMenuItem>
View Volunteer
</DropdownMenuItem>
</button>
</VolunteerProfilePopup>
</DropdownMenuContent>
</DropdownMenu>
)
},
},
]'use client'
function VolunteerProfileDialog({ volunteerId, children }) {
const { user, orgId } = useData();
const [token, setToken] = useState<string | null>(null);
const [volunteer, setVolunteer] = useState<VolunteerBaseWithId | null >(null);
const [isOpen, setIsOpen] = useState(false);
console.log("rendering VolunteerProfileDialog")
console.log("volunteerId: ", volunteerId)
useEffect(() => {
const fetchToken = async () => {
if (user) {
const fetchedToken = await getIdToken(user);
setToken(fetchedToken);
}
};
fetchToken();
}, [user]);
const {
isLoading,
error,
} = useQuery(['volunteer', volunteerId], () => fetchVolunteer(volunteerId, orgId as string, token as string), {
enabled: !!token,
onSuccess: data => {
// Do something with the data once the request is successful
setVolunteer(data.volunteer);
},
});
if (isLoading) return <Loader />;
if (error) return <ErrorScreen error={(error as Error).message} />;
if (!volunteer) return <ErrorScreen error="Volunteer not found" />;
return (
<Dialog open={isOpen}>
<DialogTrigger asChild>
<button onClick={() => setIsOpen(true)}>
{children}
</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Volunteer Profile</DialogTitle>
</DialogHeader>
<DialogDescription>
<h1>hi</h1>
</DialogDescription>
<DialogFooter>
<button>Close</button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
export default VolunteerProfileDialog@DirtyCajunRice | AppDir i tried REALLY hard to do it this way too. to fully grasp why the docs used it as an example. i came to the conclusion that it just simply is an example, but not one you should use in practice
Brown bearOP
Why do I feel like trying to do the modal page again 😅 Trying to implement modal in table is pretty frustrating