Next.js Discord

Discord Forum

Using Prisma

Answered
Silver Marten posted this in #help-forum
Open in Discord
Silver MartenOP
Hello,

I am getting worried I am not understanding the thing with Prisma, or I'm just stupid.

ChangeTeamRoleButton.tsx
type ChangeTeamRoleButtonType = {
    teamid: string,
    user: User,
    currentRole: string
}
export default async function ChangeTeamRoleButton({teamid, user, currentRole}: ChangeTeamRoleButtonType) {
    
    const handleRolechange = async (newRole) => {
        console.log(newRole) // Returns fine
        await updateTeamRole(user.id, teamid, newRole); // THIS BREAKS, since it cannot load Prisma
    }
    
  return (
    <TeamMemberRoleSelector handleChange={handleRolechange} currentRole={currentRole}/>
  )
}

And a client component (TeamMemberRoleSelector.tsx)
type TeamMemberRoleSelectorProps = {
    handleChange: (role: string) => void,
    currentRole: string
}
export default function TeamMemberRoleSelector({handleChange, currentRole}: TeamMemberRoleSelectorProps) {
  return (
    <Select defaultValue={currentRole || ""} onValueChange={handleChange}>
        <SelectTrigger className="w-[110px]">
        <SelectValue placeholder="Select" />
        </SelectTrigger>
        <SelectContent>
            <SelectItem value="Admin">Admin</SelectItem>
            <SelectItem value="Member">Member</SelectItem>
            <SelectItem value="Owner">Owner</SelectItem>
        </SelectContent>
    </Select>
  )
}


When I click the select box it sends the parameter, so that works. But when I try to call the async function updateTeamRole it just freaks out:
export async function updateTeamRole(userId: string, teamId: string, role: string) {
    const teamMember = await prisma.teamMember.findFirst({
        where: { AND:[
            { userId: userId },
            { teamId: teamId }
        ] },
    })
    // More logic
}   

Getting the following error:
Error: PrismaClient is unable to run in this browser environment, or has been bundled for the browser (running inunknown).
Answered by Silver Marten
type ChangeTeamRoleButtonType = {
    teamid: string,
    user: User,
    currentRole: string
}

export default function ChangeTeamRoleButton({teamid, user, currentRole}: ChangeTeamRoleButtonType) {
    const {toast} = useToast();
    async function handleRolechange(newRole: string) {    
        await fetch(
          checkEnvironment().concat(`/api/teams/${teamid}/permissions`),
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            cache: "no-store",
            body: JSON.stringify({
              userId: user.id,
              teamId: teamid,
              permission: newRole
            })
          }
        ).then(() => {
            toast({
                title: "Successfully updated user permissions",
                description: `User ${user.email} changed role to ${newRole}`,
                variant: "success",
              })
        })
        .catch(err => {
          toast({
            title: "Error",
            description: err.message,
            variant: "destructive",
          })
        })
    }
  return (
    <TeamMemberRoleSelector handleChange={handleRolechange} currentRole={currentRole}/>
  )
}


In case anyone was interested in the code.
View full answer

12 Replies

Silver MartenOP
Do I have to use this like an API or something else instead? Is there any alternative to API solutions?
Japanese flying squid
In terms of general help with Prisma and how to use it. I'd advise going to the Prisma Discord server https://discord.com/invite/jS3XY7vp46

But let me try and help you out. I need some more info:
- The version of Next.js u are using
- Whether you are using app/pages router
- Where is the updateTeamRole in ur folder structure?
Silver MartenOP
- Next 14.0.1
- App router (so the view in question is in /app/dashboard/teams/[teamid]/manage)
- /utils/teams.tsx > updateTeamRole
@Japanese flying squid
export default async function TeamManagePage({ params }: { params: { teamid: string } }) {
  const team: TeamAndMembers = await getTeamAndMembers(params.teamid);
  
  if(!team) return <Alert variant="destructive">No team found with id: {params.teamid}</Alert>
  return (
    <div>
      <PageTitle title="Manage Team" text={team.name ? team.name : "No team name"}/>
      <Title title="List of members"/>
      <DataTable data={team.members} columns={columns}/>
    </div>
  )
}

So this works fine, which is weird.
export async function getTeamAndMembers(id: string) {
    return await prisma.team.findFirst({
        where: {
            id: id
        },
        include: {
            members: {
                include: {
                    user: true,
                }
            }
        }
    })
}

But when I do calls to the function after pressing a button or calling on it just doesn't.
Japanese flying squid
can you link so i can view the teams.tsx, off the bat this should just be a .ts file, but I need to take a closer look to understand why it’s a .tsx file
Japanese flying squid
What does ur updateTeamRole() function return
Silver MartenOP
right now nothing, since it breaks before a return. If I try to return anything it just doesn't reach that before Next cancels it.
Japanese flying squid
Sorry. I mean what are you trying to return
If you can upload the teams.tsx and the whole function to a GitHub Gist or something similar. Then i will have more info to go off
Silver MartenOP
Fixed it by using an API, guess it doesn't like to run Prisma directly:

app/api/teams/[teamid]/permissions
// POST FUNCTION
export async function POST(req: NextRequest, res: NextResponse) {
    const {teamId, userId, permission} = await req.json();

    // Get the team that's going to be updated
    const teamToUpdate = await prisma.teamMember.findFirst({
        where: {
            teamId: teamId,
            userId: userId
        }
    })
    // If we can't find a team, return the error
    if(teamToUpdate == null) {
        return NextResponse.json({message: "Error: Team not found"}, { status: 404 });
    }
    // Update the teamMember row, with the incoming role.
    const setNewRole = await prisma.teamMember.update({
        where: {
            id: teamToUpdate.id
        },
        data: {
            teamRole: permission
        }
    })
    return NextResponse.json({setNewRole}, { status: 200 });
}
Silver MartenOP
type ChangeTeamRoleButtonType = {
    teamid: string,
    user: User,
    currentRole: string
}

export default function ChangeTeamRoleButton({teamid, user, currentRole}: ChangeTeamRoleButtonType) {
    const {toast} = useToast();
    async function handleRolechange(newRole: string) {    
        await fetch(
          checkEnvironment().concat(`/api/teams/${teamid}/permissions`),
          {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            cache: "no-store",
            body: JSON.stringify({
              userId: user.id,
              teamId: teamid,
              permission: newRole
            })
          }
        ).then(() => {
            toast({
                title: "Successfully updated user permissions",
                description: `User ${user.email} changed role to ${newRole}`,
                variant: "success",
              })
        })
        .catch(err => {
          toast({
            title: "Error",
            description: err.message,
            variant: "destructive",
          })
        })
    }
  return (
    <TeamMemberRoleSelector handleChange={handleRolechange} currentRole={currentRole}/>
  )
}


In case anyone was interested in the code.
Answer