ui
ui copied to clipboard
Error when wrapping TableRow over link in NextJS with Shadcn
On the latest version of NextJS 13 and ShadCN, the following code snippet will cause an error:
<Table>
<TableCaption>A list of instruments.</TableCaption>
<TableHeader>
<TableRow>
{headers.map((header: HeaderType) => (
<TableHead key={header.name} className={header.width}>
{header.name}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{instruments.map((instrument: InstrumentType) => (
<Link
key={instrument.instrumentId}
href={`/blog/${instrument.instrumentId}`}
>
<TableRow>
<TableCell>{instrument.instrumentId}</TableCell>
<TableCell>{instrument.instrumentName}</TableCell>
</TableRow>
</Link>
))}
</TableBody>
</Table>
Is there a workaround this? I want to make it such that when a table row is clicked, it navigates to a specific instrument based on ID.
5 errors are being thrown:
Expected server HTML to contain a matching <table> in <div>.
Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
An error occurred during hydration. The server HTML was replaced with client content in <#document>.
validateDOMNesting(...): <tr> cannot appear as a child of <a>.
Warning: validateDOMNesting(...): <a> cannot appear as a child of <tbody>.
Able to reproduce on this and also looking for a solution! For now, the easiest way to solve this is by using legacyBehavior
on the Link component, which is not pretty but gets the job done.
@itsmingjie hey, yeah using legacyBehavior=true
solves the issue, however, when you hover over the Link component, the URL preview doesnt appear. Is this the same for you?
@itsmingjie hey, yeah using
legacyBehavior=true
solves the issue, however, when you hover over the Link component, the URL preview doesnt appear. Is this the same for you?
@suenalaba I believe that's because the legacy Link component isn't actually a real DOM Element, but only a routing layer that adds an onClick
handler to its child element. See https://github.com/vercel/next.js/pull/36436 for when they discussed how they changed it from the legacy behavior to the new one.
You'll need to nest an anchor element to have the link preview display, I believe.
were you able to solve this?
were you able to solve this?
Only able to resolve it via using legacyBehavior=True
If using a client component, you can also use the router
via useRouter()
to achieve this directly on the TableRow
:
<TableRow
onClick={() => {
router.push(`/your-url`)
}}
className="cursor-pointer"
>
This doesn't provide the browser URL preview but it avoids using legacyBehavior
. I know this is basically the same thing, but at least you will have control over it, and this protects against if the legacyBehavior
attribute is removed in the future.
@shanehoban I guess if you wanted to do this without converting into a client component you could make the whole row a form with a redirect action and the whole row being a submit button, haven't tested tho, I'm ok with the legacyBehavior
for now
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.