Fix Portal

Summary:Portal keeps its opened modals as a state member. so if multiple consecutive `_showModal`
or `_closeModal` are called, it will only read the initial state and merge the end result,
which causes some close or open calls to be overwritten due to race condition.

This diff fixes such issue.

Reviewed By: dmmiller

Differential Revision: D3160561

fb-gh-sync-id: 6d936c795660b119e2d3fe8b3ab807307eca92c5
fbshipit-source-id: 6d936c795660b119e2d3fe8b3ab807307eca92c5
This commit is contained in:
Hedger Wang 2016-04-15 02:17:31 -07:00 committed by Facebook Github Bot 4
parent 719c9aa6fe
commit 7354ff33b2
1 changed files with 15 additions and 20 deletions

View File

@ -36,6 +36,8 @@ var lastUsedTag = 0;
* by the top-level `renderApplication`.
*/
var Portal = React.createClass({
_modals: {},
statics: {
/**
* Use this to create a new unique tag for your component that renders
@ -95,7 +97,8 @@ var Portal = React.createClass({
},
getInitialState: function() {
return {modals: {}};
this._modals = {};
return {};
},
_showModal: function(tag: string, component: any) {
@ -104,17 +107,13 @@ var Portal = React.createClass({
if (this._getOpenModals().length === 0) {
this.props.onModalVisibilityChanged(true);
}
// This way state is chained through multiple calls to
// _showModal, _closeModal correctly.
this.setState((state) => {
var modals = state.modals;
modals[tag] = component;
return {modals};
});
this._modals[tag] = component;
this.forceUpdate();
},
_closeModal: function(tag: string) {
if (!this.state.modals.hasOwnProperty(tag)) {
if (!this._modals.hasOwnProperty(tag)) {
return;
}
// We are about to close last modal, so Portal will disappear.
@ -122,17 +121,13 @@ var Portal = React.createClass({
if (this._getOpenModals().length === 1) {
this.props.onModalVisibilityChanged(false);
}
// This way state is chained through multiple calls to
// _showModal, _closeModal correctly.
this.setState((state) => {
var modals = state.modals;
delete modals[tag];
return {modals};
});
delete this._modals[tag];
this.forceUpdate();
},
_getOpenModals: function(): Array<string> {
return Object.keys(this.state.modals);
return Object.keys(this._modals);
},
_notifyAccessibilityService: function() {
@ -151,12 +146,12 @@ var Portal = React.createClass({
render: function() {
_portalRef = this;
if (!this.state.modals) {
if (!this._modals) {
return null;
}
var modals = [];
for (var tag in this.state.modals) {
modals.push(this.state.modals[tag]);
for (var tag in this._modals) {
modals.push(this._modals[tag]);
}
if (modals.length === 0) {
return null;