Code change:
<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>

Related discussion:
text: 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.