From 7354ff33b2a24ceebdd9cccf447738b7815ec07b Mon Sep 17 00:00:00 2001 From: Hedger Wang Date: Fri, 15 Apr 2016 02:17:31 -0700 Subject: [PATCH] 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 --- Libraries/Portal/Portal.js | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/Libraries/Portal/Portal.js b/Libraries/Portal/Portal.js index cfe278f15f6..b310b203bac 100644 --- a/Libraries/Portal/Portal.js +++ b/Libraries/Portal/Portal.js @@ -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 { - 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;