Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Invariant Violation: ReactMount: Two valid but unequal nodes with the same data-reactid" #4120

Closed
SamyPesse opened this issue Jun 13, 2015 · 10 comments

Comments

@SamyPesse
Copy link

I'm trying to display a dropdown menu composed of ul, li and a (similar to the one from bootstrap).
A PluginList element is used to generate a dropdown menu from a store.

But the browser is not correctly parsing/outputting the HTML. Everytime I click on an item, I got the error: Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the samedata-reactid: .0.0.0.0.7.1.$=15:0.0.

This bug is probably related to #1400, but I can't find any solution 😓

I'using react 0.13.3 and I also tested with the latest master.

HTML DOM View:

screen shot 2015-06-13 at 11 35 21

View of the same tree in the React plugin for Chrome:

screen shot 2015-06-13 at 11 34 37

Screenshot of the result

The blue element has nothing to do here

screen shot 2015-06-13 at 11 34 58

@SamyPesse
Copy link
Author

Use React.renderToString in PluginsList returns the valid string:

<ul class="dropdown-menu" data-reactid=".2" data-react-checksum="868905626"><li data-reactid=".2.0:$test"><a href="#" data-reactid=".2.0:$test.0"><span data-reactid=".2.0:$test.0.$=10:0">test</span><span data-reactid=".2.0:$test.0.$=11:0"> </span><span class="help-label" data-reactid=".2.0:$test.0.$=12:0">1.0.0</span></a></li><li data-reactid=".2.0:$exercises"><a href="#" data-reactid=".2.0:$exercises.0"><span data-reactid=".2.0:$exercises.0.$=10:0">exercises</span><span data-reactid=".2.0:$exercises.0.$=11:0"> </span><span class="help-label" data-reactid=".2.0:$exercises.0.$=12:0">*</span></a></li><li class="divider" data-reactid=".2.0:$divider"></li><li data-reactid=".2.1"><a href="#" data-reactid=".2.1.0"><i class="octicon octicon-plus" data-reactid=".2.1.0.$=10:0"></i><span data-reactid=".2.1.0.$=11:0"> Add Plugin</span></a></li><li data-reactid=".2.2"><a href="#" data-reactid=".2.2.0"><i class="octicon octicon-trashcan" data-reactid=".2.2.0.$=10:0"></i><span data-reactid=".2.2.0.$=11:0"> Remove Plugin</span></a></li><li data-reactid=".2.3"><a href="#" data-reactid=".2.3.0"><i class="octicon octicon-package" data-reactid=".2.3.0.$=10:0"></i><span data-reactid=".2.3.0.$=11:0"> Find Plugins</span></a></li></ul>

@SamyPesse
Copy link
Author

It looks like the error is happening when I'm using PluginsList inside DropdownItem,

This works

<div>
    <PluginsList></PluginsList>
</div>

This doesn't work

<Button.DropdownItem>
    <i className="octicon octicon-package"></i> Plugins
    <PluginsList></PluginsList>
</Button.DropdownItem>

DropdownItem is defined by:

var DropdownItem = React.createClass({
    onClick: function(e) {
        e.preventDefault();
        e.stopPropagation();
        if (this.props.onClick) this.props.onClick();
    },

    isMenu: function(child) {
        return child.type && child.type.displayName == 'DropdownMenu';
    },

    render: function() {
        if (this.props.divider) return <li className="divider"></li>;

        var inner = [], outer = [];

        inner = React.Children.map(this.props.children, function(child) {
            if (!this.isMenu(child)) return child;
            return null;
        }, this);

        outer = React.Children.map(this.props.children, function(child) {
            if (this.isMenu(child)) return child;
            return null;
        }, this);

        return <li>
            <a href="#" onClick={this.onClick}>{inner}</a>
            {outer}
        </li>
    }
});

@zpao
Copy link
Member

zpao commented Jun 13, 2015

Looking at the HTML view, the data-reactid in question is used on 2 <a> tags. Usually this is the result of the browser reorganizing nodes, specifically nested <a>s.

<a id="1">
  <a id="2">foo</a>
</a>

Will always get moved in the DOM to be

<a id="1"></a>
<a id="2">foo</a>

That's the likely culprit for your case. Chances are you have nested anchors across components. DropdownItem definitely has one. If anything rendered inside there has an anchor (I guess PluginsList or one of its children), then this will happen. When it does happen, React's idea of the DOM and the real DOM get out of sync, and then you hit this problem.

Though your problem might actually be manifesting slightly differently (could be the DOM structure playing different tricks) but you definitely have nested anchors.

@SamyPesse
Copy link
Author

Thanks @zpao 🍻

It was a stupid mistake on my side: The filtering done in DropdownItem to ensure that sub-menus are added to li instead of li > a didn't work since the child type was PluginsList instead of DropdownMenu, I was convinced that React rendered children before calling the render method of the parent.

@sophiebits
Copy link
Collaborator

React will warn for invalid nesting like this in the next release.

@SamyPesse
Copy link
Author

@spicyj I saw a comment about this on another issue, but when I tested using the latest master I didn't get any warning about invalid nesting.

@kulikalov
Copy link

What if i need this kind of nesting?

<a>
  <div>
    <a></a>
  </div>
</a>

How could I avoid this error?

@jimfb
Copy link
Contributor

jimfb commented Aug 11, 2015

@mdcsfk That kind of nesting will not trigger this error.

@sophiebits
Copy link
Collaborator

@jimfb Yes it will; you can't have two nested anchor tags in HTML.

@mdcsfk You will need to restructure your markup. You can't have that kind of nesting in HTML, whether or not you're using React. Usually you'll want to change one of the links to not be an actual link and you can add a click handler to it.

@jimfb
Copy link
Contributor

jimfb commented Aug 11, 2015

Oh, right, because the dom will rewrite the anchors. You're right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants