Change:
In this repro, I created 2 buttons and only one is rendered at a time. One button's click handler is hooked up to React's synthetic "click" event while the other is hooked up to the native "click" event. Even though only one button is rendered at a time, a single click is triggering both click events. This bug can be hit by apps that mix React components with non-React controls (e.g. jQuery UI). I reproed this in Chrome with React 0.13.2. to the button labeled "One" Expected: There's a button rendered labeled "Two" Actual: The rendered button still has the label "One" If you open the console, you'll see "goToTwo" and "goToOne" which indicates that the "One" button's click handler ran and then the "Two" button's click handler ran (even though we never saw button "Two"").
I experimented more and came up with another repro: In this one, you click on a button with a native "click" handler which causes the button to go away and an input field to be rendered. It results in this exception: From these 2 repros, it seems something strange is going on when calling from within a native "click" handler.
It works if you add to the event handler.
Thanks for the workaround. Is the behavior without the by design? It looks like the bad behavior is being caused by the rerender happening synchronously within the native "click" handler.
This looks bad. We don't do a great job interacting with native events. Sebastian wrote a post about this once-upon-a-time, how native and synthetic event systems are, by and large, not interoperable. Even so, I can't see a reason we should fatal like this. Do you understand what's going wrong here? What a fix might look like?
This happens when we handle a click event from a node that's been removed in between when the event is triggered and when React receives it. How should we deal with the case that events fire on detached elements? Should we ignore events for nodes that aren't in the document? I don't think the bug is easily fixable otherwise because we don't have the old event handler after the reconcile that removes that node.
Here are some additional details about the impact of the bug. It sounds like this bug is likely to trigger when you use a non-React component (e.g. jQuery UI) in a React single page application and the non-React component triggers a navigation within the app.
Thanks for an excellent bug report and good repro case! I think this happens because we use the "root id" to determine which element was clicked. In the repro case there is no "key" as part of the root ID for two reasons: 1) It is not a child of a container (multichild) so it doesn't get a key to the root ID. 2) It doesn't have a unique key and doesn't need one because it the button is of a different type. If I make sure that a key is used as part of the root ID the problem is solved: So the problem in the repro isn't that we're firing on a removed node, it is that we're firing the event on the new node. This would be solved if we used a unique ID per instance to identify event handlers instead of a generate root that is non-unique. Which I think we wanted to do anyway. Is there another repro that shows a different issue?

Discussion:
echo "Only docs were updated, stopping build process." exit fi <del> npm install -g npm </del> <ins> npm install -g npm@latest-2 </ins> script: - | if [ "$TEST_TYPE" = build_website ]; then

do { lastID = internalGetID(current); current = current.parentNode; <del> invariant( current != null, 'findFirstReactDOMImpl(...): Unexpected detached subtree found when ' + 'traversing DOM from node `%s`.', nodeID ); </del> <ins> if (current == null) { // The passed-in node has been detached from the container it was // originally rendered into. return null; } </ins> } while (lastID !== reactRootID); if (current === containersByReactRootID[reactRootID]) {

<ins> /** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @emails react-core */ 'use strict'; var React; var ReactDOM; var ReactTestUtils; describe('ReactEventIndependence', function() { beforeEach(function() { require('mock-modules').dumpCache(); React = require('React'); ReactDOM = require('ReactDOM'); ReactTestUtils = require('ReactTestUtils'); }); it('does not crash with other react inside', function() { var clicks = 0; var div = ReactTestUtils.renderIntoDocument( <div onClick={() => clicks++} dangerouslySetInnerHTML={{ __html: '<button data-reactid=".z">click me</div>', }} /> ); ReactTestUtils.SimulateNative.click(div.firstChild); expect(clicks).toBe(1); }); it('does not crash with other react outside', function() { var clicks = 0; var outer = document.createElement('div'); outer.setAttribute('data-reactid', '.z'); var inner = ReactDOM.render( <button onClick={() => clicks++}>click me</button>, outer ); ReactTestUtils.SimulateNative.click(inner); expect(clicks).toBe(1); }); it('does not when event fired on unmounted tree', function() { var clicks = 0; var container = document.createElement('div'); var button = ReactDOM.render( <button onClick={() => clicks++}>click me</button>, container ); // Now we unmount the component, as if caused by a non-React event handler // for the same click we're about to simulate, like closing a layer: ReactDOM.unmountComponentAtNode(container); ReactTestUtils.SimulateNative.click(button); // Since the tree is unmounted, we don't dispatch the click event. expect(clicks).toBe(0); }); }); </ins>