Next.js Discord

Discord Forum

Mantine polymorphic components with Link

Unanswered
Blood cockle posted this in #help-forum
Open in Discord
Blood cockleOP
I've tried out upgrading to Next16 today, and components which follow this pattern:

import Link from 'next/link';
import { ActionIcon } from '@mantine/core';

function Demo() {
  return <ActionIcon component={Link} href="/" />;
}


create an error like this:
Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
<... component={function LinkComponent} href=... variant=... size=... fullWidth=... h=... p=... styles=... children=...>


I'm used to that error and dealing with it when it makes sense for functions, but LinkComponent is a component.

Has something changed there in how NextJS 16 handles this case?

32 Replies

Blood cockleOP
In a server component at the top of the hierarchy. Basically in the server page controller.
@Blood cockle In a server component at the top of the hierarchy. Basically in the server page controller.
Try adding "use client" in Demo and remove "use client" in Action Icon
Blood cockleOP
Well sure, but that means I can never use a polymorphic component in a server component. Which is awkward for things that are fundamentally just a link. I don't really want to have to wrap each of them in a separate file to make them into a client component at a granular level.
if its "fundamentally" just a link why does it need to be a client component?
just make a "fundamental" component
@Blood cockle Well sure, but that means I can never use a polymorphic component in a server component. Which is awkward for things that are fundamentally just a link. I don't really want to have to wrap each of them in a separate file to make them into a client component at a granular level.
what im asking is to make "Demo" the client boundary not ActionIcon.

let ActionIcon be the polymorphic component but don't let ActionIcon as the client boundary.

this way you only need one "use client" at the top and the rest will be okay as usual
im not sure how that would lead to "warpping each of them in a separate file to make them into a client component at a granural level"

Thats the thing though, you aren't supposed to make "use client" at a granular level, you aren't supposed to just mark a client-only component with "use client"...
"use client" marks as a boundary, as a gate, it does more than converting a component into a client component
architecture-wise you need something that marks as the boundary from server->client.

usually you don't pass function from server to client no?
Blood cockleOP
The pattern that trips me up is something like this:

export async function Page() {

  const data = db.select();

  return (
    <div>
      <Paper component={Link} href="/">
        {data.title}
      </Paper>
    </div>
  )
}
you either have two options:

1.
<Paper type="link" href="/">

2.
<PaperLink href="/">

3.
<Link className="paper" href="/">

or

4.
return <PageUI data={data}> // <-- "use client"

edit:
5.
<Link href="/"><Paper>content</Paper></Link>
boy im bad at math
Blood cockleOP
There are only two hard problems in computer science:
- concurrency
- naming things
- off-by-one errors
haha
number 4 leads you to only making one extra file per route

number 3 leads you to making no extra files

number 2 leads you to making more components for every use cases

number 1 is i think over-engineered and more confusing than the rest
so what i usually ended up doing is:

start with 3,
then make it more readable into 2
with combination of 4
Blood cockleOP
<Link href="/"><Paper>content</Paper></Link> presumably also works.
sure but that is more line of codes
i will add it to the list
Blood cockleOP
It makes targeting the CSS a bit jankier as well. Which is why I was hoping there was just something I was missing there.
not to mention <Link> creates a BOX model that might ruins styling
yeah i was about to say that
i was having problem with <Form> ruining children styling the other day so i had to refactor styling around the existence of <form>
Blood cockleOP
this may be worth updating with some kind of note - it worked in 15 but now doesn't in 16.
I think it shouldn't work in 15 either. like the latest verison of 15
this code
Blood cockleOP
I'm on "next": "^15.5.6" and it seems to work. But if I upgrade to 16 it breaks.
interesting
i have confirmed your observation
Blood cockleOP
🤷‍♂️ That's what tripped me up in the first place. It made sense that it worked, and it also makes sense that it shouldn't work from a deeper technical level, but it makes less sense that it switched from working to not working.