0x4a6f4672
0x4a6f4672

Reputation: 28245

Link cannot appear as a descendant of a link

A React.js app gives the warning

Warning: validateDOMNesting(...): <a> cannot appear as a descendant of <a>. 
See Element > a > ... > a.

What does that mean? How can you prevent it? Are nested links illegal in HTML, HTML5 or React.js?

Upvotes: 30

Views: 55487

Answers (4)

Quentin
Quentin

Reputation: 943185

What does that mean?

It means that:

<a href="http://example.com">
  <span>
    <a href="http://example.net">
      ...
    </a>
  </span>
</a>

and

<a href="http://example.com">
  <a href="http://example.net">
    ...
  </a>
</a>

and similar constructs are not allowed. They don't make sense anyway.

How can you prevent it?

This isn't something that happens without someone writing code that tries to do it.

You need to find that code and change it.

Are nested links illegal in HTML, HTML5 or React.js?

They are illegal in all versions of HTML. The first DTD for HTML was published as part of HTML 2. It says:

<!ELEMENT A     - - %A.content -(A)>

The last part describes what content is allowed inside the element. The -(A) part of that means "Except for A elements".

HTML 5 is just the 2014 update to HTML. HTML 5.1 came out last year (2016). HTML 5.2 is under development.

React.js is a JavaScript library that generates an HTML DOM. The results are still (sort of) HTML.

Upvotes: 1

Sandeep Kamble
Sandeep Kamble

Reputation: 261

I was also getting this warning for my Navigation, I was using react-bootstrap to render React Router Link in NavItem.

Warning: validateDOMNesting `<a>` cannot appear as a descendant of `<a>`. 
in a (created by Link) 

Fix: Add componentClass attribute to render NavItem as <span> tag instead of <a> tag (You can use any other tag name here)

My code was

<Nav pullRight>
  <NavItem>
    <Link to="/responses">Responses</Link>
  </NavItem>
</nav>

After fix

<Nav pullRight>
  <NavItem componentClass='span'>
    <Link to="/responses">Responses</Link>
  </NavItem>
</nav>

This also messes up styling, to fix it add the following CSS

.navbar-nav span[role=button] {
  padding: 15px;
  display: inline-block;
  line-height: 20px;
}

Upvotes: 26

MarkS
MarkS

Reputation: 9

You can use a function instead of a tag:

import React from 'react';
import PropTypes from 'prop-types';
import { Link, withRouter } from 'react-router';

class SomeClass extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.redirect = this.redirect.bind(this);
  }

  redirect(target) {
    this.context.router.push("/path");
  }

  render() {
    return (
      <div>
        <p onClick={this.redirect}>Link</p>
      </div>
    );
  }
}

SomeClass.contextTypes = {
  router: PropTypes.object
};

export default SomeClass;

Be careful to use a context. I'm using a context for routing only.

class SomeClass extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.redirect = this.redirect.bind(this);
  }
}

Upvotes: 0

bowheart
bowheart

Reputation: 4676

That means:

<a href="1">
    <a href="2"></a>
</a>

Is invalid HTML. Browsers will recognize this and turn this into:

<a href="1"></a>
<a href="2"></a>

React warns you about this because the browser's fix will make the actual DOM different from the virtual DOM, leading to strange bugs when React goes to update stuff.

Heed React's warning and don't nest <a> tags.

Upvotes: 43

Related Questions