question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Back transitions are visible if you reset stack to 1st screen when switching between tabs (with react-freeze)

See original GitHub issue

Description

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

https://user-images.githubusercontent.com/22820318/141129470-cb650049-49bb-4d57-a803-e5de80270601.mov

Freeze disabled

https://user-images.githubusercontent.com/22820318/141129663-40e7b44a-3a58-4c75-a77c-2fbd366d8910.mov

Steps To Reproduce

  1. Open TabA
  2. Go to Screen2
  3. Go to Screen3
  4. Open TabB
  5. 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:closed
  • Created 2 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
kirillzyuskocommented, Nov 24, 2021

Hi @kacperkapusciak

Yes, sure, I will check a little bit later 😃

0reactions
kirillzyuskocommented, Dec 2, 2021

@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 🙂

Read more comments on GitHub >

github_iconTop Results From Across the Web

Back transitions are visible if you reset stack to 1st screen ...
Back transitions are visible if you reset stack to 1st screen when switching between tabs (with react-freeze)
Read more >
How to reset tab stack when you come back to a ...
If you don't want the CommunityReply screen to show when you navigate back to ... Resets tabs with stackNavigators to the first route...
Read more >
Reset stack from other stack inside tab · Issue #2291
From A, I want to move to Tab2 and reset stack to [C,D] ... redirected to second screen of History stack, then if...
Read more >
Experimenting with React Freeze
Today we are publishing a new React package — react-freeze. ... which “screens” are visible and which are hidden down the stack hierarchy....
Read more >
React Navigation v5: Reset Stack Inside Tab After Leaving ...
Reset a stack navigator to the initial screen when leaving that tab. Uses React Navigation v5.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found