Next.js Discord

Discord Forum

Component rendering incorrectly when Link is present

Unanswered
Yacare Caiman posted this in #help-forum
Open in Discord
Yacare CaimanOP
The expected behavior for my website is that these cards render like in the first image, but it's rendering like in the second image (for the first two seconds, which causes a hydration error).

Here's the snippet of code which makes the error happen:

<p className="text-neutral-400 font-semibold text-xs">
  {authors.map((author, i) =>
    <span key={i}>
      <Link
        href={`/artist/test`}
        className="hover:underline"
      >
        {author}
      </Link>
      {i < authors.length - 1 && (
        ', '
      )}
    </span>
  )}
</p>


The thing that causes the cards to render wrong is the "Link" component, the author's in the card are supposed to be routable, but when adding the Link, it screws the whole component up. The third image shows how it renders in the html (the content being outside of the <a> tag).

24 Replies

Polar bear
show me the hydration error
Yacare CaimanOP
sure, give me a sec
I get these three everytime I refresh the page
try adding a useEffect that first checks if the component is mounted before mapping the data
@Dayo try adding a useEffect that first checks if the component is mounted before mapping the data
Yacare CaimanOP
Oh, I'll look up how to do that thanks!
@Dayo https://nextjs.org/docs/messages/react-hydration-error
Yacare CaimanOP
thanks!!
Here's the simplified page:

import Body from "@/components/layout/Body"
import AlbumCard from "@/components/card/AlbumCard"

export default async function Home() {
    const albums = [
        { id: "blah", name: "blah", image: "blah", authors: ["blah", "blah2"] }
    ]
    return (
        <>
            <div
                className="absolute z-0 inset-x-0 h-96 rounded-t-[--radius] bg-gradient-to-b from-purple-950 to-transparent"
            />
            <Body>
                <h2 className="mt-4 text-white text-2xl font-bold">Latest releases</h2>
                <div className="grid grid-cols-1 gap-4 @xs:grid-cols-2 @md:grid-cols-3 @2xl:grid-cols-4 @4xl:grid-cols-5 @5xl:grid-cols-6 @6xl:grid-cols-7">
                    {albums.map(album =>
                        <AlbumCard
                            key={album.id}
                            name={album.name}
                            href={`/album/${album.id}`}
                            image={album.image}
                            authors={album.authors}
                        />
                    )}
                </div>
            </Body>
        </>
    )
}
Yacare CaimanOP
And here's the AlbumCard component:

export default function GenreCard({
    name,
    authors,
    image,
    href,
}: Props) {
    return (
        <Link
            href={href}
            draggable="false"
            className="h-full"
        >
            <div className="group p-4 pb-6 flex flex-col bg-neutral-900 hover:bg-neutral-800 transition-colors gap-2 rounded-[--radius] overflow-hidden">
                <div className="relative aspect-square transition-transform group-hover:-translate-y-1">
                    <Image
                        src={image}
                        alt={"blah"}
                        fill
                    />
                </div>
                <h2 className="mt-2 truncate overflow-hidden text-white text-md font-bold drop-shadow-xl">
                    {name}
                </h2>
                <p className="text-neutral-400 font-semibold text-xs">
                    {authors.map((author, i) =>
                        <span key={i}>
                            <Link
                                href={`/artist/test`}
                                className="hover:underline"
                            >
                                {author}
                            </Link>
                            {i < authors.length - 1 && (
                                ', '
                            )}
                        </span>
                    )}
                </p>
            </div>
        </Link>
    )
}
you have to rewrite it so that the link elements are not nested
@Yacare Caiman It renders a main tag so yeah there's no duplicate of body tag
yes then that part is good, the error is due to the Link being descendant of Link
Yacare CaimanOP
It initially renders wrong and then shows it the way I intended, but yeah it causes the hydration error
@joulev you have to rewrite it so that the link elements are not nested
Yacare CaimanOP
Thank you so much I was really confused!
@Yacare Caiman It initially renders wrong and then shows it the way I intended, but yeah it causes the hydration error
it's because i think initially the renderer would put the nested Link outside the parent Link, making them siblings, hence messing up the display on initial render
well I'll fix it right now, thanks again!
you're welcome! good luck and have fun