Reputation: 28060
So I have this example to show the issue I am running into with some code I am working on right now (can't post the exact code for numerous reasons).
http://codepen.io/anon/pen/jPxzar
var Test1 = React.createClass({
getInitialState: function() {
return {
events: ['Demo loaded'],
buttonClicked: false
};
},
componentWillMount: function() {
document.addEventListener('click', this.onDocumentClick);
},
onDocumentClick: function() {
var message = 'on document click event (button clicked: ' + this.state.buttonClicked + ')';
this.setState({
events: this.state.events.concat([message]),
buttonClicked: false
});
},
onButtonClick: function() {
this.setState({
events: this.state.events.concat(['on button click event']),
buttonClicked: true
});
},
render: function() {
return (
<span>
<button onClick={this.onButtonClick}>Button</button>
<div>Events:</div>
<ul>
{this.state.events.map(function(message) {
return <li>{message}</li>;
})}
</ul>
</span>
);
}
});
React.render(
<Test1 />,
document.getElementById('mount-point'));
Here I have a component that in the mounting of adds a native click event handler on the document as I need to track any click that happens anywhere on the page, not just within this component. I also have a button that has a ReactJS event handler. If I click anywhere outside of the button, everything works fine. If I click the button, both events are fired however the native event is fired first and then the React event however I need the React event to be triggered first.
How can I make sure that natively attached events are always executed after React events?
Upvotes: 4
Views: 2165
Reputation: 49
Based on my debugging experience, there are two click event handlers are already registered on "root" element before the actual component tree is rendered. So, any dom event listeners on "root" element are added from index 2. So, always the react events are fired first and then dom events on "root" element.
Upvotes: 2
Reputation: 12966
It appears that the events are being fired in the order that the listeners were added. I did some digging and found some information in the DOM3 spec that seems to support this, but I'm still not quite sure what the intended behavior is supposed to be.
In any case, I tested my theory and it appears to give the desired effect: http://codepen.io/anon/pen/EjLRbK
To summarize: you're currently creating the native event listener in componentWillMount
. This function executes before the component's initial call to render
, so the native event listener is created first. If you change this to componentDidMount
, it will execute after the initial call to render
, and the event listener in render
will be created first, and will be called first when clicking the button in your example code.
Upvotes: 0