Nested `<a>` tags causing validateDOMNesting warning in clickable article

15 replies
Last updated: Nov 12, 2021
I'm trying to make whole article clickable, but got the warning: Warning: validateDOMNesting(...): &lt;a&gt; cannot appear as a descendant of &lt;a&gt; AND Warning: Expected server HTML to contain a matching &lt;figure&gt; in &lt;a&gt;.

components/HeroPost/index.js
import CoverImage from '../../CoverImage';
import Link from '../../Link';
import SectionSeparator from '../../SectionSeparator';
import React from 'preact/compat';


export default function HeroPost({
                                     coverImage,
                                     slug,
                                     displayExcerpt,
                                     displayTitle,
                                 }) {
    return (
        <div className="front-container" data-row-id='1'>
            <div className="row-grid-container">
                <Link href={`/posts/${slug}`}>

                    <CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/>
                    <div className="title-container">
                        <p className="excerpt">{displayExcerpt}</p>
                        <h3 className="title">
                            <a>{displayTitle}</a>
                        </h3>

                    </div>
                </Link>

            </div>
            <SectionSeparator/>
        </div>

    );
};

components/PostPreview/index.js:

import CoverImage from '../../CoverImage';
import Link from '../../Link';
import {imageBuilder} from '../../../lib/sanity';

export default function PostPreview({
                                        title,
                                        coverImage,
                                        slug,
                                        displayTitle,
                                        displayExcerpt,
                                    }) {
    return (
        <article>
            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title">
                    <a className='hover:underline'>{displayTitle}</a>
                </h3>
            </Link>
        </article>
    );
}
If i put Link over &lt;h3&gt; i will not get the warning, but then the article is not clickable, only the img and title.


I found this:

This is the code which causing the error,

<NavLink href="#x"><Link id="RouterNavLink" style={None} to="/contact">anywords</Link></NavLink>
Which is converted to,

<a><a></a></a>
So you are getting error,

Warning: validateDOMNesting(…): <a> cannot appear as a descendant of <a>
To solve this just use one of the follow,

<NavLink id="RouterNavLink" style={None} to="/contact">anywords</NavLink>
OR,

<Link id="RouterNavLink" style={None} to="/contact">anywords</Link>
but i'm not sure how to apply this in this code, i might need a work around or structure the code differently. Hope there is someone here who can help, thanks!
AI Update

This is a React/Next.js nested anchor tag issue, not specifically a Sanity problem, but I can help you solve it!

The warning is happening because you have nested <a> tags - your Link component wraps everything, and then inside it you have another <a> tag in your <h3>. HTML doesn't allow <a> tags to be nested inside other <a> tags.

Solution: Remove the inner <a> tags

For HeroPost component:

export default function HeroPost({
    coverImage,
    slug,
    displayExcerpt,
    displayTitle,
}) {
    return (
        <div className="front-container" data-row-id='1'>
            <div className="row-grid-container">
                <Link href={`/posts/${slug}`}>
                    <CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/>
                    <div className="title-container">
                        <p className="excerpt">{displayExcerpt}</p>
                        <h3 className="title">
                            {displayTitle}  {/* Remove the <a> tag here */}
                        </h3>
                    </div>
                </Link>
            </div>
            <SectionSeparator/>
        </div>
    );
}

For PostPreview component:

export default function PostPreview({
    title,
    coverImage,
    slug,
    displayTitle,
    displayExcerpt,
}) {
    return (
        <article>
            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title hover:underline">
                    {displayTitle}  {/* Remove the <a> tag here */}
                </h3>
            </Link>
        </article>
    );
}

Why this works:

  • The outer Link component already renders as an <a> tag that wraps all the content
  • Everything inside it (image, excerpt, title) becomes clickable automatically
  • You don't need inner <a> tags at all
  • Move any styling classes (like hover:underline) directly to the <h3> or to the Link component itself

The entire card/article will now be clickable without any nesting warnings. This is the standard pattern for making card-style components fully clickable in React/Next.js applications.

Show original thread
15 replies
This seems like more of a React issue not a sanity one, but it seems like you might have an anchor
<a>
tag nested within another
<a>
tag.What is the code for your
Link
?
The Link:

import React from 'react'
import NextLink from 'next/link'

interface Props {
    children: Array<JSX.Element | string | null> | JSX.Element | string | null
    className?: string
    href: string
    target?: string
    rel?: string
    onClick?: (event: React.MouseEvent<Element, MouseEvent>) => void
}

const Link: React.FC<Props> = ({ children, href, className, target, rel, onClick }) => {
    // @ts-ignore
    function handleClick(e) {
        if (e.type === 'click' || e.key === 'Enter') {
            onClick?.(e)
        }
    }

    return (
        <NextLink href={href}>
            <a
                className={className}
                target={target}
                rel={rel}
                {...(onClick
                    ? {
                        onClick,
                        onKeyPress: handleClick,
                        role: 'link',
                        tabIndex: 0,
                    }
                    : {})}
            >
                {children}
            </a>
        </NextLink>
    )
}

export default Link

Yeah so you've got two nested
a
tags here. The
a
tag that sits in your
Link
component, and then another one that lives in the
children


            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title">
                    <a className='hover:underline'>{displayTitle}</a>
                </h3>
            </Link>

to fix, just change
<a className='hover:underline'>{displayTitle}</a>
to
<span className='hover:underline'>{displayTitle}</span>
and do the same anywhere else you've used a nested anchor tag
i'm still getting the warning, unfortunately 😞
    return (
        <div className="front-container" data-row-id='1'>
            <div className="row-grid-container">
                <Link href={`/posts/${slug}`}>

                    <CoverImage slug={slug} imageObject={coverImage} title={displayTitle} url={coverImage}/>
                    <div className="title-container">
                        <p className="excerpt">{displayExcerpt}</p>
                        <h3 className="title">
                            <span>{displayTitle}</span>
                        </h3>

                    </div>
                </Link>

            </div>
            <SectionSeparator/>
        </div>

    );
};
and


    return (
        <article>
            <Link href={`/posts/${slug}`}>
                <div className="image-container">
                    <CoverImage slug={slug} title={title} imageObject={coverImage}
                                url={imageBuilder(coverImage).url()}/>
                </div>
                <p className="excerpt">{displayExcerpt}</p>
                <h3 className="title">
                    <span className='hover:underline'>{displayTitle}</span>
                </h3>
            </Link>
        </article>
    );
}
The
validateDOMNesting
warning?
It looks like you're passing a url to
CoverImage
does this component contain another anchor tag?
yes, Warning: validateDOMNesting(...): &lt;a&gt; cannot appear as a descendant of &lt;a&gt;. and Warning: Expected server HTML to contain a matching &lt;figure&gt; in &lt;a&gt;.
Ah wait that's the image url
Your best bet is to check the rendered code to see if there's another &lt;a&gt; tag nested anywhere
You're passing a slug to
CoverImage
so maybe there's an
a
tag in there afterall
yes, thanks. It was the CoverImage. I changed it to span too and that fixed my problem. Thank you!
No problem 🙂 in future you're probably better asking for help in a dedicated web dev server such as Reactiflux
https://www.reactiflux.com/
Awesome, thanks!

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?