react: "Can only update a mounted or mounting component." - reactjs

The setState call in question is working despite the warning. The warning only occurs after the component on which I am calling setState has been removed, and then rerendered. Why am I getting this warning when the component is already mounted?
<div id="contentArea">
{this.state.activePlugin?this.state.activePlugin.render():null}
</div>
the render method returns a react element:
render(){
return <DatasetsList />;
}
state.activePlugin is set to null and the component containing the jsx code above is rerendered, this is how removing the 'activePlugin' happens. When render is called again and returns the <DatasetsList /> for the second time, subsequent clicks inside the component produce this warning, despite the fact that the setState calls they initiate in fact work as expected.
In other words, the warning appears to be misleading, as the code is working as expected.
componentDidMount() {
this.unsubscribe = this.props.store.listen(s=>{
this.setState(s);
});
}

https://jsfiddle.net/taylorallred/69z2wepo/29874/
var Hello = React.createClass({
getInitialState: function() {
return {
activePlugin: Plugin
}
},
togglePlugin: function() {
this.setState({
activePlugin: this.state.activePlugin ? null : Plugin
})
},
render: function() {
return <div >
< div onClick = {
this.togglePlugin
} > Hello {
this.props.name
} < /div> < div > {
this.state.activePlugin ? < Plugin / > : null
} < /div> < /div>;
}
});
var Plugin = React.createClass({
render: function() {
return ( < MyComponent / > );
}
});
var MyComponent = React.createClass({
getInitialState:function(){
return {a: 1};
},
componentDidMount:function(){
window.setInterval(function(that){that.setState({a: that.state.a++})}, 2000, this);
},
render: function() {
var a = this.state.a;
return <div > MyComponent { a }< /div>;
}
});
ReactDOM.render( < Hello name = "World" / > ,
document.getElementById('container')
);
It's probably because your component is receiving updates when it's not rendered and that component is trying to render because it's state changed. See the fiddle. Click to remove the component and you'll get that error in the console.

The warning was referring to the old unmounted instance of my component which was still listening to the store, as shown in the question. Simply unsubscribing from the store inside componentWillUnmount solved the issue.
componentWillUnmount() {
this.unsubscribe();
}

Related

Unable to set state in the component

When the click event takes place, the state is not set to the value given inside the CompOne. It still show the initial state and console logs the old state which is "hello".
var CompOne = React.createClass({
getInitialState: function() {
return {
edit: "hello"
}
},
editme: function () {
this.setState({
edit: "there"
})
console.log(this.state.edit)
},
render: function(){
return (
<div>
{this.props.name}
<button onClick={this.editme}>Edit</button>
</div>
)
}
})
var Pri = React.createClass({
render: function () {
return (
<div>
< CompOne name = "Anne"/>
< CompOne name = "Bob"/>
</div>
);
}
})
ReactDOM.render( <Pri /> , document.getElementById("root"));
Function setState is not synchronous. Here is a note about this from React documentation;
setState() does not immediately mutate this.state but creates a
pending state transition. Accessing this.state after calling this
method can potentially return the existing value. There is no
guarantee of synchronous operation of calls to setState and calls
may be batched for performance gains.
In human terms this means that if you call setState and try to read the state immediately, the state could be changed or it could be the same.
The solution that you can use is to pass a callback to setState method as a second parameter:
editme: function () {
this.setState({
edit: "there"
}, function(){
// this function would be invoked only when the state is changed
console.log(this.state.edit);
});
}
The purpose of the second parameter is described in the same documentation article:
The second parameter is an optional callback function that will be
executed once setState is completed and the component is
re-rendered.
You need to use the callback function in setState because setState takes time to mutate and you console.log gets executed before the state is mutated as statements are executed asynchronously.
editme: function () {
this.setState({
edit: "there"
}, function(){
console.log(this.state.edit)
})
},
var CompOne = React.createClass({
getInitialState: function() {
return {
edit: "hello"
}
},
editme: function () {
this.setState({
edit: "there"
}, function(){
console.log(this.state.edit)
})
},
render: function(){
return (
<div>
{this.props.name}
<button onClick={this.editme}>Edit</button>
</div>
)
}
})
var Pri = React.createClass({
render: function () {
return (
<div>
< CompOne name = "Anne"/>
< CompOne name = "Bob"/>
</div>
);
}
})
ReactDOM.render( <Pri /> , document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="root"></div>

Global variable in Reactjs

How can I have a global variable in a component that all the methods have access to it? I can't use the state because I have nested rendering and by changing the state of a variable I'm getting the warning that the render should be pure and don't use the setState inside render....! So I need to have a regular global variable accessible by all methods of the component and be able to change the value of it wherever is needed. Can anyone help me please?
P.S. Why I shouldn't change a state like this: this.state.variable = true;?
So here is my simplified code. this.setState({hidden: true}); will make the warning because this component is rendering inside another component. I need to make hidden to behave like a global variable and don't use the state!
const Component = React.createClass({
mixins: [React.addons.PureRenderMixin],
getInitialState: function() {
return {hidden: false};
},
renderFixedFields(.....) {
var request_link;
if (!this.state.hidden) {
request_link = <Link to={`/${record.get('id')}/request`}>Send Request </Link>
}
else {
request_link = null
}
return (
<div>
{request_link}
</div>
)
},
renderField(.....) {
var self = this;
//....
if (fieldID == "open_access") {
this.setState({hidden: true});
}
return (
//.....
);
},
renderFieldBlock(........) {
const [maj, min] = getMajMinFields(s);
//....
const minFields = min.entrySeq().map(
([id, f]) => this.renderField(fieldID, .....));
return (
//...
<div>
{ minorFields }
</div>
);
},
}
Setting state inside of render() is always going to be an issue as state changing will issue a render(). While the specific thing you are doing may not cause an issue, you should really be thinking about the lifecycle of your component and where that state really needs to change. If you need to change state based on new props then use componentWillReceiveProps:
componentWillReceiveProps: function(nextProps) {
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}

How do I set state of sibling components easily in React?

I have got the beginnings of a clickable list component that will serve to drive a select element. As you can see from the below, onClick of the ListItem, I'm passing the state of a child element (ListItem in this case) to the parents (SelectableList, and CustomSelect component). This is working fine. However, what I would also like to do is change the state of the sibling components (the other ListItems) so that I can toggle their selected states when one of the ListItems is clicked.
At the moment, I'm simply using document.querySelectorAll('ul.cs-select li) to grab the elements and change the class to selected when it doesn't match the index of the clicked ListItem. This works - to an extent. However, after a few clicks, the state of the component has not been updated by React (only by client side JS), and things start to break down. What I would like to do is change the this.state.isSelected of the sibling list items, and use this state to refresh the SelectableList component. Could anyone offer a better alternative to what I've written below?
var React = require('react');
var SelectBox = require('./select-box');
var ListItem = React.createClass({
getInitialState: function() {
return {
isSelected: false
};
},
toggleSelected: function () {
if (this.state.isSelected == true) {
this.setState({
isSelected: false
})
} else {
this.setState({
isSelected: true
})
}
},
handleClick: function(listItem) {
this.toggleSelected();
this.props.onListItemChange(listItem.props.value);
var unboundForEach = Array.prototype.forEach,
forEach = Function.prototype.call.bind(unboundForEach);
forEach(document.querySelectorAll('ul.cs-select li'), function (el) {
// below is trying to
// make sure that when a user clicks on a list
// item in the SelectableList, then all the *other*
// list items get class="selected" removed.
// this works for the first time that you move through the
// list clicking the other items, but then, on the second
// pass through, starts to fail, requiring *two clicks* before the
// list item is selected again.
// maybe there's a better more "reactive" method of doing this?
if (el.dataset.index != listItem.props.index && el.classList.contains('selected') ) {
el.classList.remove('selected');
}
});
},
render: function() {
return (
<li ref={"listSel"+this.props.key}
data-value={this.props.value}
data-index={this.props.index}
className={this.state.isSelected == true ? 'selected' : '' }
onClick={this.handleClick.bind(null, this)}>
{this.props.content}
</li>
);
}
});
var SelectableList = React.createClass({
render: function() {
var listItems = this.props.options.map(function(opt, index) {
return <ListItem key={index} index={index}
value={opt.value} content={opt.label}
onListItemChange={this.props.onListItemChange.bind(null, index)} />;
}, this);
return <ul className="cs-select">{ listItems }</ul>;
}
})
var CustomSelect = React.createClass({
getInitialState: function () {
return {
selectedOption: ''
}
},
handleListItemChange: function(listIndex, listItem) {
this.setState({
selectedOption: listItem.props.value
})
},
render: function () {
var options = [{value:"One", label: "One"},{value:"Two", label: "Two"},{value:"Three", label: "Three"}];
return (
<div className="group">
<div className="cs-select">
<SelectableList options={options}
onListItemChange={this.handleListItemChange} />
<SelectBox className="cs-select"
initialValue={this.state.selectedOption}
fieldName="custom-select" options={options}/>
</div>
</div>
)
}
})
module.exports = CustomSelect;
The parent component should pass a callback to the children, and each child would trigger that callback when its state changes. You could actually hold all of the state in the parent, using it as a single point of truth, and pass the "selected" value down to each child as a prop.
In that case, the child could look like this:
var Child = React.createClass({
onToggle: function() {
this.props.onToggle(this.props.id, !this.props.selected);
},
render: function() {
return <button onClick={this.onToggle}>Toggle {this.props.label} - {this.props.selected ? 'Selected!' : ''}!</button>;
}
});
It has no state, it just fires an onToggle callback when clicked. The parent would look like this:
var Parent = React.createClass({
getInitialState: function() {
return {
selections: []
};
},
onChildToggle: function(id, selected) {
var selections = this.state.selections;
selections[id] = selected;
this.setState({
selections: selections
});
},
buildChildren: function(dataItem) {
return <Child
id={dataItem.id}
label={dataItem.label}
selected={this.state.selections[dataItem.id]}
onToggle={this.onChildToggle} />
},
render: function() {
return <div>{this.props.data.map(this.buildChildren)}</div>
}
});
It holds an array of selections in state and when it handles the callback from a child, it uses setState to re-render the children by passing its state down in the selected prop to each child.
You can see a working example of this here:
https://jsfiddle.net/fth25erj/
Another strategy for sibling-sibling communication is to use observer pattern.
The Observer Pattern is a software design pattern in which an object can send messages to multiple other objects.
No sibling or parent-child relationship is required to use this strategy.
Within the context of React, this would mean some components subscribe to receive particular messages and other components publish messages to those subscribers.
Components would typically subscribe in the componentDidMount method and unsubscribe in the componentWillUnmount method.
Here are 4 libraries that implement the Observer Pattern. The differences between them are subtle - EventEmitter is the most popular.
PubSubJS: "a topic-based publish/subscribe library written in JavaScript."
EventEmitter: "Evented JavaScript for the browser." It's actually an implementation of a library that already exists as part of nodejs core, but for the browser.
MicroEvent.js: "event emitter microlibrary - 20lines - for node and browser"
mobx: "Simple, scalable state management."
Taken from: 8 no-Flux strategies for React component communication which also is a great read in general.
The following code helps me to setup communication between two siblings. The setup is done in their parent during render() and componentDidMount() calls.
class App extends React.Component<IAppProps, IAppState> {
private _navigationPanel: NavigationPanel;
private _mapPanel: MapPanel;
constructor() {
super();
this.state = {};
}
// `componentDidMount()` is called by ReactJS after `render()`
componentDidMount() {
// Pass _mapPanel to _navigationPanel
// It will allow _navigationPanel to call _mapPanel directly
this._navigationPanel.setMapPanel(this._mapPanel);
}
render() {
return (
<div id="appDiv" style={divStyle}>
// `ref=` helps to get reference to a child during rendering
<NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
<MapPanel ref={(child) => { this._mapPanel = child; }} />
</div>
);
}
}

What is the proper way to getInitialState with remote data in Reactjs?

IT IS SOLVED. The code was ok, the problem was with improper import.
It is a long post (due to code samples). I'll appreciate your patience and will be very thankful for your help!
We have a RoR back-end and React on the front-end and we are using alt as an implementation of flux. We also use babel to compile ES6 to ES5. So the problem is that I can not render component due to 2 errors.
First is Uncaught TypeError: Cannot read property 'map' of undefined
It appears on the render function of MapPalette component:
render() {
return (
<div>
{this.state.featureCategories.map(fc => <PaletteItemsList featureCategory={fc} />)}
</div>
);
}
And the second is Uncaught Error: Invariant Violation: receiveComponent(...): Can only update a mounted component.
So here is the whole MapPalette component
"use strict";
import React from 'react';
import PaletteItemsList from './PaletteItemsList';
import FeatureCategoryStore from '../stores/FeatureTypeStore';
function getAppState() {
return {
featureCategories: FeatureCategoryStore.getState().featureCategories
};
}
var MapPalette = React.createClass({
displayName: 'MapPalette',
propTypes: {
featureSetId: React.PropTypes.number.isRequired
},
getInitialState() {
return getAppState();
},
componentDidMount() {
FeatureCategoryStore.listen(this._onChange);
},
componentWillUnmount() {
FeatureCategoryStore.unlisten(this._onChange);
},
render() {
return (
<div>
{this.state.featureCategories.map(fc => <PaletteItemsList featureCategory={fc} />)}
</div>
);
},
_onChange() {
this.setState(getAppState());
}
});
module.exports = MapPalette;
FeatureCategoryStore
var featureCategoryStore = alt.createStore(class FeatureCategoryStore {
constructor() {
this.bindActions(FeatureCategoryActions)
this.featureCategories = [];
}
onReceiveAll(featureCategories) {
this.featureCategories = featureCategories;
}
})
module.exports = featureCategoryStore
FeatureCategoryActions
class FeatureCategoryActions {
receiveAll(featureCategories) {
this.dispatch(featureCategories)
}
getFeatureSetCategories(featureSetId) {
var url = '/feature_categories/nested_feature_types.json';
var actions = this.actions;
this.dispatch();
request.get(url)
.query({ feature_set_id: featureSetId })
.end( function(response) {
actions.receiveAll(response.body);
});
}
}
module.exports = alt.createActions(FeatureCategoryActions);
And the last - how I render React component.
var render = function() {
FeatureCategoryActions.getFeatureSetCategories(#{ #feature_set.id });
React.render(
React.createElement(FeatureSetEditMap, {featureSetId: #{#feature_set.id}}),
document.getElementById('react-app')
)
}
First of all, the first error you get:
Uncaught TypeError: Cannot read property 'map' of undefined
Is because this.state in your component is undefined, which means that you probably haven't implemented getInitialState in your component.
You haven't included the full implementation of your component, which we need to see to be able to help you. But let's walk through their example of a view component:
var LocationComponent = React.createClass({
getInitialState() {
return locationStore.getState()
},
componentDidMount() {
locationStore.listen(this.onChange)
},
componentWillUnmount() {
locationStore.unlisten(this.onChange)
},
onChange() {
this.setState(this.getInitialState())
},
render() {
return (
<div>
<p>
City {this.state.city}
</p>
<p>
Country {this.state.country}
</p>
</div>
)
}
})
They implement getInitialState here to return the current state of the store, which you'll then be able to use in the render method. In componentDidMount, they listen to change events from that store so that any events occuring in that store coming from anywhere in your application will trigger a re-render. componentWillUnmount cleans up the event listener. Very important not to forget this, or your app will leak memory! Next the onChange method (which could be have whatever name, it's not an internal React method), which the store will call when a change event occurs. This just sets the state of the component to whatever the stores state is. Might be a bit confusing that they call getInitialState again here, because you're not getting the initial state, you're getting the current state of the store.
Another important note here is that this example won't work off the bat with ES6/ES2015 classes, because React no longer autobinds methods to the instance of the component. So the example implemented as a class would look something like this:
class LocationComponent extends React.Component {
constructor(props) {
super(props)
this.state = this.getState();
this.onChangeListener = () => this.setState(this.getState());
}
getState() {
return locationStore.getState();
}
componentDidMount() {
locationStore.listen(this.onChangeListener);
}
componentWillUnmount() {
locationStore.unlisten(this.onChangeListener)
}
render() {
return (
<div>
<p>
City {this.state.city}
</p>
<p>
Country {this.state.country}
</p>
</div>
);
}
}
Sorry for your wasted time on reading it, but I figured it out and the reason of trouble was my silly mistake in importing. Essentially, I've imported another Store with the name of needed.
So, instead of import FeatureCategoryStore from '../stores/FeatureTypeStore';
It should be import FeatureCategoryStore from '../stores/FeatureCategoryStore';

How to listen for click events that are outside of a component

I want to close a dropdown menu when a click occurs outside of the dropdown component.
How do I do that?
Using the life-cycle methods add and remove event listeners to the document.
React.createClass({
handleClick: function (e) {
if (this.getDOMNode().contains(e.target)) {
return;
}
},
componentWillMount: function () {
document.addEventListener('click', this.handleClick, false);
},
componentWillUnmount: function () {
document.removeEventListener('click', this.handleClick, false);
}
});
Check out lines 48-54 of this component: https://github.com/i-like-robots/react-tube-tracker/blob/91dc0129a1f6077bef57ea4ad9a860be0c600e9d/app/component/tube-tracker.jsx#L48-54
In the element I have added mousedown and mouseup like this:
onMouseDown={this.props.onMouseDown} onMouseUp={this.props.onMouseUp}
Then in the parent I do this:
componentDidMount: function () {
window.addEventListener('mousedown', this.pageClick, false);
},
pageClick: function (e) {
if (this.mouseIsDownOnCalendar) {
return;
}
this.setState({
showCal: false
});
},
mouseDownHandler: function () {
this.mouseIsDownOnCalendar = true;
},
mouseUpHandler: function () {
this.mouseIsDownOnCalendar = false;
}
The showCal is a boolean that when true shows in my case a calendar and false hides it.
Look at the target of the event, if the event was directly on the component, or children of that component, then the click was inside. Otherwise it was outside.
React.createClass({
clickDocument: function(e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
// Inside of the component.
} else {
// Outside of the component.
}
},
componentDidMount: function() {
$(document).bind('click', this.clickDocument);
},
componentWillUnmount: function() {
$(document).unbind('click', this.clickDocument);
},
render: function() {
return (
<div ref='component'>
...
</div>
)
}
});
If this is to be used in many components, it is nicer with a mixin:
var ClickMixin = {
_clickDocument: function (e) {
var component = React.findDOMNode(this.refs.component);
if (e.target == component || $(component).has(e.target).length) {
this.clickInside(e);
} else {
this.clickOutside(e);
}
},
componentDidMount: function () {
$(document).bind('click', this._clickDocument);
},
componentWillUnmount: function () {
$(document).unbind('click', this._clickDocument);
},
}
See example here: https://jsfiddle.net/0Lshs7mg/1/
For your specific use case, the currently accepted answer is a tad over-engineered. If you want to listen for when a user clicks out of a dropdown list, simply use a <select> component as the parent element and attach an onBlur handler to it.
The only drawbacks to this approach is that it assumes the user has already maintained focus on the element, and it relies on a form control (which may or may not be what you want if you take into account that the tab key also focuses and blurs elements) - but these drawbacks are only really a limit for more complicated use cases, in which case a more complicated solution might be necessary.
var Dropdown = React.createClass({
handleBlur: function(e) {
// do something when user clicks outside of this element
},
render: function() {
return (
<select onBlur={this.handleBlur}>
...
</select>
);
}
});
I have written a generic event handler for events that originate outside of the component, react-outside-event.
The implementation itself is simple:
When component is mounted, an event handler is attached to the window object.
When an event occurs, the component checks whether the event originates from within the component. If it does not, then it triggers onOutsideEvent on the target component.
When component is unmounted, the event handler is detacthed.
import React from 'react';
import ReactDOM from 'react-dom';
/**
* #param {ReactClass} Target The component that defines `onOutsideEvent` handler.
* #param {String[]} supportedEvents A list of valid DOM event names. Default: ['mousedown'].
* #return {ReactClass}
*/
export default (Target, supportedEvents = ['mousedown']) => {
return class ReactOutsideEvent extends React.Component {
componentDidMount = () => {
if (!this.refs.target.onOutsideEvent) {
throw new Error('Component does not defined "onOutsideEvent" method.');
}
supportedEvents.forEach((eventName) => {
window.addEventListener(eventName, this.handleEvent, false);
});
};
componentWillUnmount = () => {
supportedEvents.forEach((eventName) => {
window.removeEventListener(eventName, this.handleEvent, false);
});
};
handleEvent = (event) => {
let target,
targetElement,
isInside,
isOutside;
target = this.refs.target;
targetElement = ReactDOM.findDOMNode(target);
isInside = targetElement.contains(event.target) || targetElement === event.target;
isOutside = !isInside;
if (isOutside) {
target.onOutsideEvent(event);
}
};
render() {
return <Target ref='target' {... this.props} />;
}
}
};
To use the component, you need wrap the target component class declaration using the higher order component and define the events that you want to handle:
import React from 'react';
import ReactDOM from 'react-dom';
import ReactOutsideEvent from 'react-outside-event';
class Player extends React.Component {
onOutsideEvent = (event) => {
if (event.type === 'mousedown') {
} else if (event.type === 'mouseup') {
}
}
render () {
return <div>Hello, World!</div>;
}
}
export default ReactOutsideEvent(Player, ['mousedown', 'mouseup']);
I voted up one of the answers even though it didn't work for me. It ended up leading me to this solution. I changed the order of operations slightly. I listen for mouseDown on the target and mouseUp on the target. If either of those return TRUE, we don't close the modal. As soon as a click is registered, anywhere, those two booleans { mouseDownOnModal, mouseUpOnModal } are set back to false.
componentDidMount() {
document.addEventListener('click', this._handlePageClick);
},
componentWillUnmount() {
document.removeEventListener('click', this._handlePageClick);
},
_handlePageClick(e) {
var wasDown = this.mouseDownOnModal;
var wasUp = this.mouseUpOnModal;
this.mouseDownOnModal = false;
this.mouseUpOnModal = false;
if (!wasDown && !wasUp)
this.close();
},
_handleMouseDown() {
this.mouseDownOnModal = true;
},
_handleMouseUp() {
this.mouseUpOnModal = true;
},
render() {
return (
<Modal onMouseDown={this._handleMouseDown} >
onMouseUp={this._handleMouseUp}
{/* other_content_here */}
</Modal>
);
}
This has the advantage that all the code rests with the child component, and not the parent. It means that there's no boilerplate code to copy when reusing this component.
Create a fixed layer that spans the whole screen (.backdrop).
Have the target element (.target) outside the .backdrop element and with a greater stacking index (z-index).
Then any click on the .backdrop element will be considered "outside of the .target element".
.click-overlay {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
}
.target {
position: relative;
z-index: 2;
}
Here is an example: http://jsfiddle.net/LHmwd/
More on the discussion: https://github.com/facebook/react/issues/579
You could use refs to achieve this, something like the following should work.
Add the ref to your element:
<div ref={(element) => { this.myElement = element; }}></div>
You can then add a function for handling the click outside of the element like so:
handleClickOutside(e) {
if (!this.myElement.contains(e)) {
this.setState({ myElementVisibility: false });
}
}
Then finally, add and remove the event listeners on will mount and will unmount.
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false); // assuming that you already did .bind(this) in constructor
}
Super late to the party, but I've had success with setting a blur event on the parent element of the dropdown with the associated code to close the dropdown, and also attaching a mousedown listener to the parent element that checks if the dropdown is open or not, and will stop the event propagation if it is open so that the blur event won't be triggered.
Since the mousedown event bubbles up this will prevent any mousedown on children from causing a blur on the parent.
/* Some react component */
...
showFoo = () => this.setState({ showFoo: true });
hideFoo = () => this.setState({ showFoo: false });
clicked = e => {
if (!this.state.showFoo) {
this.showFoo();
return;
}
e.preventDefault()
e.stopPropagation()
}
render() {
return (
<div
onFocus={this.showFoo}
onBlur={this.hideFoo}
onMouseDown={this.clicked}
>
{this.state.showFoo ? <FooComponent /> : null}
</div>
)
}
...
e.preventDefault() shouldn't have to be called as far as I can reason but firefox doesn't play nice without it for whatever reason. Works on Chrome, Firefox, and Safari.
I found a simpler way about this.
You just need to add onHide(this.closeFunction) on the modal
<Modal onHide={this.closeFunction}>
...
</Modal>
Assuming you have a function to close the modal.
Use the excellent react-onclickoutside mixin:
npm install --save react-onclickoutside
And then
var Component = React.createClass({
mixins: [
require('react-onclickoutside')
],
handleClickOutside: function(evt) {
// ...handling code goes here...
}
});

Resources