From 080813e0cf5e6562290334adc4b565ad46a45782 Mon Sep 17 00:00:00 2001 From: "Davis Z. Cabral" Date: Wed, 6 Jun 2018 10:24:23 -0300 Subject: [PATCH] popTo causes an infinite loop when route is not found (as seen on #3026) (#3043) * popTo causes an infinite loop when route is not found (as seen on #3026) * Added warning --- Example/package.json | 2 +- __tests__/scenes.test.js | 2 ++ dist/Reducer.js | 7 ++++++- package.json | 2 +- src/Reducer.js | 8 ++++++++ 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Example/package.json b/Example/package.json index ecf602a3a..dbde5dc09 100644 --- a/Example/package.json +++ b/Example/package.json @@ -16,7 +16,7 @@ "react-native": "0.55.4", "react-native-button": "^2.0.0", "react-native-message-bar": "^1.6.0", - "react-native-router-flux": "4.0.0-beta.31", + "react-native-router-flux": "4.0.0-beta.32", "react-navigation": "1.5.8" }, "devDependencies": { diff --git a/__tests__/scenes.test.js b/__tests__/scenes.test.js index 912fa943d..879dab580 100644 --- a/__tests__/scenes.test.js +++ b/__tests__/scenes.test.js @@ -25,5 +25,7 @@ test('renders correctly', done => { console.log('STATE:', JSON.stringify(navigationStore.state)); navigationStore.refresh({ a: 3 }); console.log('STATE:', JSON.stringify(navigationStore.state)); + navigationStore.popTo('NOT_A_REAL_SCENE'); + console.log('STATE:', JSON.stringify(navigationStore.state)); done(); }); diff --git a/dist/Reducer.js b/dist/Reducer.js index 8ba270c4f..0c98eca15 100644 --- a/dist/Reducer.js +++ b/dist/Reducer.js @@ -16,6 +16,7 @@ Object.defineProperty(exports,"__esModule",{value:true});exports.supportedAction + reducer=reducer;exports.default= @@ -70,6 +71,10 @@ reducer=reducer;exports.default= -createReducer;var _navigationStore=require('./navigationStore');var _navigationStore2=_interopRequireDefault(_navigationStore);var _ActionConst=require('./ActionConst');var ActionConst=_interopRequireWildcard(_ActionConst);var _reactNavigation=require('react-navigation');var _State=require('./State');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}var supportedActions=exports.supportedActions=(_supportedActions={},_defineProperty(_supportedActions,ActionConst.PUSH,_reactNavigation.NavigationActions.NAVIGATE),_defineProperty(_supportedActions,ActionConst.BACK,_reactNavigation.NavigationActions.BACK),_defineProperty(_supportedActions,ActionConst.REFRESH,_reactNavigation.NavigationActions.BACK),_defineProperty(_supportedActions,ActionConst.RESET,_reactNavigation.NavigationActions.RESET),_supportedActions);var createAction=function createAction(type){return function(){var payload=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};return _extends({type:type},payload);};};function reducer(){var state=arguments.length>0&&arguments[0]!==undefined?arguments[0]:_navigationStore2.default.state;var action=arguments[1];var type=action.type;var routeName=action.routeName;if(supportedActions[type]){var newState=_navigationStore2.default.router.getStateForAction(createAction(supportedActions[type])({routeName:routeName,params:action.params}),state);return newState||state;}if(type===ActionConst.JUMP){var _newState=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:routeName,params:action.params}),state);var activeState=(0,_State.getActiveState)(state);if(activeState.routeName==='DrawerOpen'){activeState=(0,_State.getActiveStateExceptDrawer)(state);if((0,_State.isActiveRoute)(state,routeName)){return _navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:'DrawerClose'}),state);}}if((0,_State.isActiveRoute)(state,routeName)){return state;}var key=(0,_State.getActiveState)(_newState).key;return _navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.setParams({key:key,params:action.params}),_newState);}else if(type===ActionConst.POP_TO){var nextScene='';var _newState2=state;var currentState=state;while(_newState2&&nextScene!==routeName){_newState2=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.back(),currentState);if(_newState2){nextScene=(0,_State.getActiveState)(_newState2).routeName;if(nextScene!==routeName){currentState=_newState2;}}}return nextScene===routeName?_newState2:state;}else if(type===ActionConst.REPLACE){var _newState3=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:routeName,params:action.params}),state);return(0,_State.popPrevious)(_newState3);}return _navigationStore2.default.router.getStateForAction(action,state)||state;}function createReducer(){ + + + + +createReducer;var _lodash=require('lodash.isequal');var _lodash2=_interopRequireDefault(_lodash);var _navigationStore=require('./navigationStore');var _navigationStore2=_interopRequireDefault(_navigationStore);var _ActionConst=require('./ActionConst');var ActionConst=_interopRequireWildcard(_ActionConst);var _reactNavigation=require('react-navigation');var _State=require('./State');function _interopRequireWildcard(obj){if(obj&&obj.__esModule){return obj;}else{var newObj={};if(obj!=null){for(var key in obj){if(Object.prototype.hasOwnProperty.call(obj,key))newObj[key]=obj[key];}}newObj.default=obj;return newObj;}}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj};}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}var supportedActions=exports.supportedActions=(_supportedActions={},_defineProperty(_supportedActions,ActionConst.PUSH,_reactNavigation.NavigationActions.NAVIGATE),_defineProperty(_supportedActions,ActionConst.BACK,_reactNavigation.NavigationActions.BACK),_defineProperty(_supportedActions,ActionConst.REFRESH,_reactNavigation.NavigationActions.BACK),_defineProperty(_supportedActions,ActionConst.RESET,_reactNavigation.NavigationActions.RESET),_supportedActions);var createAction=function createAction(type){return function(){var payload=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};return _extends({type:type},payload);};};function reducer(){var state=arguments.length>0&&arguments[0]!==undefined?arguments[0]:_navigationStore2.default.state;var action=arguments[1];var type=action.type;var routeName=action.routeName;if(supportedActions[type]){var newState=_navigationStore2.default.router.getStateForAction(createAction(supportedActions[type])({routeName:routeName,params:action.params}),state);return newState||state;}if(type===ActionConst.JUMP){var _newState=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:routeName,params:action.params}),state);var activeState=(0,_State.getActiveState)(state);if(activeState.routeName==='DrawerOpen'){activeState=(0,_State.getActiveStateExceptDrawer)(state);if((0,_State.isActiveRoute)(state,routeName)){return _navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:'DrawerClose'}),state);}}if((0,_State.isActiveRoute)(state,routeName)){return state;}var key=(0,_State.getActiveState)(_newState).key;return _navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.setParams({key:key,params:action.params}),_newState);}else if(type===ActionConst.POP_TO){var nextScene='';var _newState2=state;var currentState=state;var initialState=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.popToTop(),currentState);while(_newState2&&nextScene!==routeName){_newState2=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.back(),currentState);if(_newState2){nextScene=(0,_State.getActiveState)(_newState2).routeName;if(nextScene!==routeName){currentState=_newState2;}if((0,_lodash2.default)(currentState,initialState)){break;}}}return nextScene===routeName?_newState2:state;}else if(type===ActionConst.REPLACE){var _newState3=_navigationStore2.default.router.getStateForAction(_reactNavigation.NavigationActions.navigate({routeName:routeName,params:action.params}),state);return(0,_State.popPrevious)(_newState3);}return _navigationStore2.default.router.getStateForAction(action,state)||state;}function createReducer(){ return reducer; } \ No newline at end of file diff --git a/package.json b/package.json index f8fe4026f..d6c32d3c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-router-flux", - "version": "4.0.0-beta.31", + "version": "4.0.0-beta.32", "description": "React Native Router using Flux architecture", "repository": { "type": "git", diff --git a/src/Reducer.js b/src/Reducer.js index 3859d38d9..b79ec4281 100644 --- a/src/Reducer.js +++ b/src/Reducer.js @@ -1,3 +1,4 @@ +import isEqual from 'lodash.isequal'; import navigationStore from './navigationStore'; import * as ActionConst from './ActionConst'; import { NavigationActions } from 'react-navigation'; @@ -50,6 +51,7 @@ export function reducer(state = navigationStore.state, action) { let nextScene = ''; let newState = state; let currentState = state; + const initialState = navigationStore.router.getStateForAction(NavigationActions.popToTop(), currentState); while (newState && nextScene !== routeName) { newState = navigationStore.router.getStateForAction(NavigationActions.back(), currentState); if (newState) { @@ -57,6 +59,12 @@ export function reducer(state = navigationStore.state, action) { if (nextScene !== routeName) { currentState = newState; } + if (isEqual(currentState, initialState)) { + console.warn( + `popTo called with an unknown routeName: ${routeName}`, + ); + break; + } } } return nextScene === routeName ? newState : state;