Back transitions are visible if you reset stack to 1st screen when switching between tabs (with react-freeze)
See original GitHub issueDescription
If we have TabNavigator with following structure:
|--TabA
|----Screen1
|----Screen2
|----Screen3
|--TabB
|----ScreenB
and we have a requirement to reset stack to the first screen, if user switches between tabs, then enabling react-freeze
causes some issues (transition becomes visible).
I understand, that with enabled react-freeze
we are skipping rendering for not visible screens and it may be kind of expected behavior (we skip rendering -> animation will be skipped as well). But just want to hear your opinion on how to overcome
this problem and what are the possible ways for solving it.
I think it’s quite common requirement to reset stack to first screen, when user switches between tabs. But unfortunately react-freeze
adds undesired behavior and makes it impossible to use this nice feature for entire app (maybe we can enable it selectively per screen via special prop, like detachInactiveScreens
but add a special one for freeze
functionality?).
Anyway, thank you for your hard work and new ideas! I will be pleased to hear your thoughts on this topic 😊
Screenshots
Freeze enabled
Freeze disabled
Steps To Reproduce
- Open
TabA
- Go to
Screen2
- Go to
Screen3
- Open
TabB
- Open
TabA
Expected behavior
You should see Screen1
immediately
Actual behavior
You see transition from Screen3
to Screen1
Reproduction
Sorry, the code is dirty, but I think you understand the idea.
import React from 'react';
import {View, Text, Button} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {createStackNavigator} from '@react-navigation/stack';
const Tab = createBottomTabNavigator();
function Screen1({navigation}) {
return (
<View
style={{
backgroundColor: 'green',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{color: 'white'}}>Screen 1</Text>
<Button
onPress={() => navigation.navigate('Screen2')}
title="Go to Screen 2"
/>
</View>
);
}
function Screen2({navigation}) {
return (
<View
style={{
backgroundColor: 'red',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{color: 'white'}}>Screen 2</Text>
<Button
onPress={() => navigation.navigate('Screen3')}
title="Go to Screen 3"
/>
</View>
);
}
function Screen3() {
return (
<View
style={{
backgroundColor: 'blue',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<Text style={{color: 'white'}}>Screen 3</Text>
</View>
);
}
function ScreenB() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>Screen B</Text>
</View>
);
}
const Stack = createStackNavigator();
function TabAStack() {
return (
<Stack.Navigator initialRouteName="Screen1">
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
<Stack.Screen name="Screen3" component={Screen3} />
</Stack.Navigator>
);
}
export const maybePopToTop = navigation => {
const state = navigation.getState().routes;
const stackWithState = state.filter(stack => stack.state);
if (
stackWithState.length &&
stackWithState.some(route => route.state?.index !== 0)
) {
navigation.popToTop();
}
};
const listeners = ({navigation}) => ({
tabPress: () => {
maybePopToTop(navigation);
},
});
const MainStack = createStackNavigator();
const Tabs = () => (
<Tab.Navigator>
<Tab.Screen name="TabA" component={TabAStack} listeners={listeners} />
<Tab.Screen name="TabB" component={ScreenB} listeners={listeners} />
</Tab.Navigator>
);
function App() {
return (
<NavigationContainer>
<MainStack.Navigator>
<MainStack.Screen name="Tabs" component={Tabs} />
</MainStack.Navigator>
</NavigationContainer>
);
}
export default App;
Platform
- iOS
- Android
- Web
- Windows
- tvOS
Workflow
- Managed workflow
- Bare workflow
Package versions
package | version |
---|---|
react-native | 0.66.3 |
@react-navigation/native | 6.0.6 |
@react-navigation/native-stack | 6.2.5 |
react-native-screens | 3.9.0 |
react-native-safe-area-context | 3.3.2 |
react-native-gesture-handler | 1.10.3 |
react-native-reanimated | 2.2.4 |
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (5 by maintainers)
Hi @kacperkapusciak
Yes, sure, I will check a little bit later 😃
@kacperkapusciak thank you for your reply. We’ve already disabled “freeze” integration from
react-native-screens
and managed to write our custom HOC which satisfy to our project requirements (it’s also give us an ability to use it only where we need). So thank you anyway for clarification and your work on fixing reported issue. I appreciate it 🙂