Closed Flammae closed 5 years ago
Does this happen on latest version?
Your reproducible sample code doesn't have anything to repro the issue.
I installed the latest version of tab view less than a week ago.
My point was that the bug is in the code that is provided in the documentation and it happens in the current release, as you can see in snack. I'd write more about my environment, but the exact same thing happens in the snack emulator as on my device
React Native Environment Info:
System:
OS: Windows 10
CPU: (4) x64 Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Memory: 2.85 GB / 7.87 GB
Binaries:
Yarn: 1.3.2 - ~\AppData\Roaming\npm\yarn.CMD
npm: 5.8.0 - C:\Program Files\nodejs\npm.CMD
IDEs:
Android Studio: Version 3.4.0.0 AI-183.6156.11.34.5522156
I installed the latest version of tab view less than a week ago
doesn't matter. there was a regression in the version you mentioned and you need to update to the latest version to check if it happens there
My point was that the bug is in the code that is provided in the documentation and it happens in the current release, as you can see in snack
The snack doesn't have a ScrollView like you mentioned in your issue. I'm not sure how I should test?
just downloaded 2.6.1 build. The bug is still there.
about ScrollView, I was confusing for no reason. what I meant was I discovered the issue on scrollview and I spent much time debugging with ScrollView in mind, but I think problem here is TabView's gesture capture logic, because the bug also happens when you make swipe up gesture on a View component: <View style={[styles.scene, { backgroundColor: "#ff4081" }]} />
in the code, for example.
I've also not written swipe logic. I just interact with screen with swipe up gesture instead of swipe sideways on TabView component and it causes the TabBar buttons to not respond. the code I shared is all the code needed to reproduce the bug.
in the video I am sending, I change screens by swiping (first two interactions), than by clicking the buttons (second two), than I do swipe up on the pink screen and after that buttons no longer change tabs.
I can't repro this on my Android device. Can you provide a git repo with the bug?
What device and Android version do you see it on?
This happens to me too. Android only. tested on Pixel 2, Xiaomi A2, Samsung Galaxy S7. using tab-view 2.6.1
@beqaMeqvabishvili - What React Native version are you? Mine is 0.57. I'm going to try it on RN latest, will update.
Some more insights - I just ran your snack, and the bug reproduces there. I created a react-native project with your demo, on RN 0.59.8, and the bug doesn't reproduce. So it's either expo causing this, or RN version that is different than 0.59.8.
@osdnk could this be related to your recent changes?
@oriharel can you check if this happens with 2.5.0?
I'm on RN 0.59.9
, 2.6.1
and the issue reproduces to me too.
@calintamas - is this an expo project?
@oriharel no
Tested with 2.5.0
too. Same thing.
@satya164 - You got it!! doesn't reproduce on 2.5.0.
@calintamas that's weird - I wasn't able to reproduce this outside of expo
@oriharel on my side, it seems to happen on 2.5.0 too. Whenever I interact with the view (scroll, tap on an input, etc), tapping on the tab bar is no longer working
@calintamas - are you sure you're on 2.5.0? (check with your yarn.lock file)
thanks everyone for testing and providing more info. I think I have found the issue. I'll send a PR in a moment and it'll be great if someone could test if it works for them.
@oriharel indeed, it was the cache. works on 2.5.0 🎉
can you check if the change in #810 fixes it for you?
@satya164 - can you help me with this? I tried to do:
"react-native-tab-view": "satya164/fix-tab-change#942a72d"
in package.json, but apparently it's not the way. how do I point to your commit?
I think "react-native-tab-view": "github:react-native-community/react-native-tab-view#1cefb27"
should be enough.
This gives me error:
/react-native-tab-view/package.json
was successfully found. However, this package itself specifies a main
module field that could not be resolved (/Users/oriharel/code/kne.mobile/node_modules/react-native-tab-view/lib/module/index.js
hmm weird.
you can copy this to node_modules/react-native-tab-view/lib/module/Pager.js
import _extends from"@babel/runtime/helpers/extends";import _objectSpread from"@babel/runtime/helpers/objectSpread";import _slicedToArray from"@babel/runtime/helpers/slicedToArray";import _classCallCheck from"@babel/runtime/helpers/classCallCheck";import _createClass from"@babel/runtime/helpers/createClass";import _possibleConstructorReturn from"@babel/runtime/helpers/possibleConstructorReturn";import _getPrototypeOf from"@babel/runtime/helpers/getPrototypeOf";import _inherits from"@babel/runtime/helpers/inherits";var _jsxFileName="/Users/satya/Workspace/Projects/react-native-tab-view/src/Pager.tsx";import*as React from'react';import{StyleSheet,Keyboard,I18nManager}from'react-native';import{PanGestureHandler,State}from'react-native-gesture-handler';import Animated,{Easing}from'react-native-reanimated';import memoize from'./memoize';var Clock=Animated.Clock,Value=Animated.Value,onChange=Animated.onChange,and=Animated.and,abs=Animated.abs,add=Animated.add,block=Animated.block,call=Animated.call,ceil=Animated.ceil,clockRunning=Animated.clockRunning,cond=Animated.cond,divide=Animated.divide,eq=Animated.eq,event=Animated.event,floor=Animated.floor,greaterThan=Animated.greaterThan,lessThan=Animated.lessThan,max=Animated.max,min=Animated.min,multiply=Animated.multiply,neq=Animated.neq,not=Animated.not,round=Animated.round,set=Animated.set,spring=Animated.spring,startClock=Animated.startClock,stopClock=Animated.stopClock,sub=Animated.sub,timing=Animated.timing;var TRUE=1;var FALSE=0;var NOOP=0;var UNSET=-1;var DIRECTION_LEFT=1;var DIRECTION_RIGHT=-1;var SWIPE_DISTANCE_MINIMUM=20;var SWIPE_VELOCITY_IMPACT=0.01;var SPRING_CONFIG={stiffness:1000,damping:500,mass:3,overshootClamping:true,restDisplacementThreshold:0.01,restSpeedThreshold:0.01};var TIMING_CONFIG={duration:200,easing:Easing.out(Easing.cubic)};var Pager=function(_React$Component){_inherits(Pager,_React$Component);function Pager(){var _getPrototypeOf2;var _this;_classCallCheck(this,Pager);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}_this=_possibleConstructorReturn(this,(_getPrototypeOf2=_getPrototypeOf(Pager)).call.apply(_getPrototypeOf2,[this].concat(args)));_this.clock=new Clock();_this.velocityX=new Value(0);_this.gestureX=new Value(0);_this.gestureState=new Value(State.UNDETERMINED);_this.offsetX=new Value(0);_this.progress=new Value(_this.props.navigationState.index*_this.props.layout.width*DIRECTION_RIGHT);_this.index=new Value(_this.props.navigationState.index);_this.nextIndex=new Value(UNSET);_this.lastEnteredIndex=new Value(_this.props.navigationState.index);_this.isSwiping=new Value(FALSE);_this.isSwipeGesture=new Value(FALSE);_this.routesLength=new Value(_this.props.navigationState.routes.length);_this.layoutWidth=new Value(_this.props.layout.width);_this.swipeVelocityImpact=new Value(_this.props.swipeVelocityImpact||SWIPE_VELOCITY_IMPACT);_this.position=cond(_this.layoutWidth,divide(multiply(_this.progress,-1),_this.layoutWidth),_this.index);_this.springConfig={damping:new Value(_this.props.springConfig.damping!==undefined?_this.props.springConfig.damping:SPRING_CONFIG.damping),mass:new Value(_this.props.springConfig.mass!==undefined?_this.props.springConfig.mass:SPRING_CONFIG.mass),stiffness:new Value(_this.props.springConfig.stiffness!==undefined?_this.props.springConfig.stiffness:SPRING_CONFIG.stiffness),restSpeedThreshold:new Value(_this.props.springConfig.restSpeedThreshold!==undefined?_this.props.springConfig.restSpeedThreshold:SPRING_CONFIG.restSpeedThreshold),restDisplacementThreshold:new Value(_this.props.springConfig.restDisplacementThreshold!==undefined?_this.props.springConfig.restDisplacementThreshold:SPRING_CONFIG.restDisplacementThreshold)};_this.timingConfig={duration:new Value(_this.props.timingConfig.duration!==undefined?_this.props.timingConfig.duration:TIMING_CONFIG.duration)};_this.initialVelocityForSpring=new Value(0);_this.currentIndexValue=_this.props.navigationState.index;_this.pendingIndexValue=undefined;_this.enterListeners=[];_this.jumpToIndex=function(index){_this.isSwipeGesture.setValue(FALSE);_this.nextIndex.setValue(index);};_this.jumpTo=function(key){var navigationState=_this.props.navigationState;var index=navigationState.routes.findIndex(function(route){return route.key===key;});if(navigationState.index===index){_this.jumpToIndex(index);}else{_this.props.onIndexChange(index);}};_this.addListener=function(type,listener){switch(type){case'enter':_this.enterListeners.push(listener);break;}};_this.removeListener=function(type,listener){switch(type){case'enter':{var _index=_this.enterListeners.indexOf(listener);if(_index>-1){_this.enterListeners.splice(_index,1);}break;}}};_this.handleEnteredIndexChange=function(_ref){var _ref2=_slicedToArray(_ref,1),value=_ref2[0];var index=Math.max(0,Math.min(value,_this.props.navigationState.routes.length-1));_this.enterListeners.forEach(function(listener){return listener(index);});};_this.transitionTo=function(index){var toValue=new Value(0);var frameTime=new Value(0);var state={position:_this.progress,time:new Value(0),finished:new Value(FALSE)};return block([cond(clockRunning(_this.clock),NOOP,[set(toValue,multiply(index,_this.layoutWidth,DIRECTION_RIGHT)),set(frameTime,0),set(state.time,0),set(state.finished,FALSE),set(_this.index,index),startClock(_this.clock)]),cond(_this.isSwipeGesture,[cond(not(clockRunning(_this.clock)),I18nManager.isRTL?set(_this.initialVelocityForSpring,multiply(-1,_this.velocityX)):set(_this.initialVelocityForSpring,_this.velocityX)),spring(_this.clock,_objectSpread({},state,{velocity:_this.initialVelocityForSpring}),_objectSpread({},SPRING_CONFIG,_this.springConfig,{toValue:toValue}))],timing(_this.clock,_objectSpread({},state,{frameTime:frameTime}),_objectSpread({},TIMING_CONFIG,_this.timingConfig,{toValue:toValue}))),cond(state.finished,[set(_this.isSwipeGesture,FALSE),set(_this.gestureX,0),set(_this.velocityX,0),stopClock(_this.clock)])]);};_this.handleGestureEvent=event([{nativeEvent:{translationX:_this.gestureX,velocityX:_this.velocityX,state:_this.gestureState}}]);_this.velocitySignum=cond(_this.velocityX,divide(abs(_this.velocityX),_this.velocityX),0);_this.extrapolatedPosition=add(_this.gestureX,multiply(_this.velocityX,_this.velocityX,_this.velocitySignum,_this.swipeVelocityImpact));_this.translateX=block([onChange(_this.index,call([_this.index],function(_ref3){var _ref4=_slicedToArray(_ref3,1),value=_ref4[0];_this.currentIndexValue=value;if(value!==_this.props.navigationState.index){_this.props.onIndexChange(value);_this.pendingIndexValue=value;_this.forceUpdate();}})),onChange(_this.position,cond(I18nManager.isRTL?lessThan(_this.gestureX,0):greaterThan(_this.gestureX,0),cond(neq(floor(_this.position),_this.lastEnteredIndex),[set(_this.lastEnteredIndex,floor(_this.position)),call([floor(_this.position)],_this.handleEnteredIndexChange)]),cond(neq(ceil(_this.position),_this.lastEnteredIndex),[set(_this.lastEnteredIndex,ceil(_this.position)),call([ceil(_this.position)],_this.handleEnteredIndexChange)]))),onChange(_this.isSwiping,call([_this.isSwiping],function(_ref5){var _ref6=_slicedToArray(_ref5,1),value=_ref6[0];var _this$props=_this.props,keyboardDismissMode=_this$props.keyboardDismissMode,onSwipeStart=_this$props.onSwipeStart,onSwipeEnd=_this$props.onSwipeEnd;if(value===TRUE){onSwipeStart&&onSwipeStart();if(keyboardDismissMode==='on-drag'){Keyboard.dismiss();}}else{onSwipeEnd&&onSwipeEnd();}})),onChange(_this.nextIndex,cond(neq(_this.nextIndex,UNSET),[cond(clockRunning(_this.clock),stopClock(_this.clock)),set(_this.gestureX,0),set(_this.index,_this.nextIndex),set(_this.nextIndex,UNSET)])),cond(eq(_this.gestureState,State.ACTIVE),[cond(_this.isSwiping,NOOP,[set(_this.isSwiping,TRUE),set(_this.isSwipeGesture,TRUE),set(_this.offsetX,_this.progress)]),set(_this.progress,I18nManager.isRTL?sub(_this.offsetX,_this.gestureX):add(_this.offsetX,_this.gestureX)),stopClock(_this.clock)],[set(_this.isSwiping,FALSE),_this.transitionTo(cond(and(_this.gestureX,greaterThan(abs(_this.extrapolatedPosition),divide(_this.layoutWidth,2))),round(min(max(0,sub(_this.index,cond(greaterThan(_this.velocitySignum,0),I18nManager.isRTL?DIRECTION_RIGHT:DIRECTION_LEFT,I18nManager.isRTL?DIRECTION_LEFT:DIRECTION_RIGHT))),sub(_this.routesLength,1))),_this.index))]),_this.progress]);_this.getTranslateX=memoize(function(layoutWidth,routesLength,translateX){return multiply(min(max(multiply(layoutWidth,sub(routesLength,1),DIRECTION_RIGHT),translateX),0),I18nManager.isRTL?-1:1);});return _this;}_createClass(Pager,[{key:"componentDidUpdate",value:function componentDidUpdate(prevProps){var _this$props2=this.props,navigationState=_this$props2.navigationState,layout=_this$props2.layout,swipeVelocityImpact=_this$props2.swipeVelocityImpact,springConfig=_this$props2.springConfig,timingConfig=_this$props2.timingConfig;var index=navigationState.index,routes=navigationState.routes;if(index!==prevProps.navigationState.index&&index!==this.currentIndexValue||typeof this.pendingIndexValue==='number'&&index!==this.pendingIndexValue){this.jumpToIndex(index);}this.pendingIndexValue=undefined;if(prevProps.navigationState.routes.length!==routes.length){this.routesLength.setValue(routes.length);}if(prevProps.layout.width!==layout.width){this.progress.setValue(-index*layout.width);this.layoutWidth.setValue(layout.width);}if(prevProps.swipeVelocityImpact!==swipeVelocityImpact){this.swipeVelocityImpact.setValue(swipeVelocityImpact!=null?swipeVelocityImpact:SWIPE_VELOCITY_IMPACT);}if(prevProps.springConfig!==springConfig){this.springConfig.damping.setValue(springConfig.damping!==undefined?springConfig.damping:SPRING_CONFIG.damping);this.springConfig.mass.setValue(springConfig.mass!==undefined?springConfig.mass:SPRING_CONFIG.mass);this.springConfig.stiffness.setValue(springConfig.stiffness!==undefined?springConfig.stiffness:SPRING_CONFIG.stiffness);this.springConfig.restSpeedThreshold.setValue(springConfig.restSpeedThreshold!==undefined?springConfig.restSpeedThreshold:SPRING_CONFIG.restSpeedThreshold);this.springConfig.restDisplacementThreshold.setValue(springConfig.restDisplacementThreshold!==undefined?springConfig.restDisplacementThreshold:SPRING_CONFIG.restDisplacementThreshold);}if(prevProps.timingConfig!==timingConfig){this.timingConfig.duration.setValue(timingConfig.duration!==undefined?timingConfig.duration:TIMING_CONFIG.duration);}}},{key:"render",value:function render(){var _this2=this;var _this$props3=this.props,layout=_this$props3.layout,navigationState=_this$props3.navigationState,swipeEnabled=_this$props3.swipeEnabled,children=_this$props3.children,removeClippedSubviews=_this$props3.removeClippedSubviews,gestureHandlerProps=_this$props3.gestureHandlerProps;var translateX=this.getTranslateX(this.layoutWidth,this.routesLength,this.translateX);return children({position:this.position,addListener:this.addListener,removeListener:this.removeListener,jumpTo:this.jumpTo,render:function render(children){return React.createElement(PanGestureHandler,_extends({enabled:layout.width!==0&&swipeEnabled,onGestureEvent:_this2.handleGestureEvent,onHandlerStateChange:_this2.handleGestureEvent,activeOffsetX:[-SWIPE_DISTANCE_MINIMUM,SWIPE_DISTANCE_MINIMUM],failOffsetY:[-SWIPE_DISTANCE_MINIMUM,SWIPE_DISTANCE_MINIMUM]},gestureHandlerProps,{__source:{fileName:_jsxFileName,lineNumber:602}}),React.createElement(Animated.View,{removeClippedSubviews:removeClippedSubviews,style:[styles.container,layout.width?{width:layout.width*navigationState.routes.length,transform:[{translateX:translateX}]}:null],__source:{fileName:_jsxFileName,lineNumber:610}},children));}});}}]);return Pager;}(React.Component);Pager.defaultProps={swipeVelocityImpact:SWIPE_VELOCITY_IMPACT};export{Pager as default};var styles=StyleSheet.create({container:{flex:1,flexDirection:'row'}});
//# sourceMappingURL=Pager.js.map
@satya164 I copied changes from your commit by hand, it does not seem to fix the issue
where did you copy it? the published package uses compiled code. my commit has uncompiled code.
node_modules/react-native-tab-view/package.json
and node_modules/react-native-tab-view/src/Pager.tsx
@beqaMeqvabishvili that won't work since metro will use the compiled version. please copy according to my comment https://github.com/react-native-community/react-native-tab-view/issues/809#issuecomment-503454465
tried to install from this repo github:react-native-community/react-native-tab-view#942a72d
gives me the follow error: npm ERR! Command failed: C:\Program Files\Git\cmd\git.EXE checkout 942a72d npm ERR! error: pathspec '942a72d' did not match any file(s) known to git.
oh ok. no need to change anything in my project's package.json?
@satya164 It worked! thank you
I had the same issue on 2.5.0, 2.6.0 and 2.6.1 with RN 0.59.5 and no expo. The changes in your comment fixed it (https://github.com/react-native-community/react-native-tab-view/issues/809#issuecomment-503454465)
Will there be a new version including this fix soon?
I'm waiting for a review from @osdnk. We'll do a release after.
For now you can downgrade to 2.5.0
which doesn't have the issue. If you are experiencing the issue with that version, then try clearing cache (react-native start --reset-cache
or expo start -c
).
I've also set 2.5.0
as latest on npm so any new installs will install that version.
Bug
A "Quick start" code freezes on the selected tab after a vertical gesture on a TabView. The code there uses regular View elements but the same thing happens when you have scrollable components as a child.
Environment info
Device: Every Android Device (afaik)
Library version: ^2.6.0
Steps To Reproduce
Play with tabs. Switch with buttons. Switch with gestures. So far it works. Now make a vertical gesture like scrolling. The selected tab should freeze, buttons do not do anything until you change the tab by swiping.
Reproducible sample code
https://snack.expo.io/@beqa/tab-view-example-not-working