Home > Software engineering >  Maximum depth exceeded: how to define a stack for a tab?
Maximum depth exceeded: how to define a stack for a tab?

Time:12-14

I tried following React-Navigation tutorial to implement Stack Navigator Within a Tab Navigator in React Native application using expo.

I am trying to achieve the following RootStack (Stack Navigator)

  • Home (Screen)
  • Login (Screen)
  • ConsumerApp (Tab Navigator)
    • SettingsStackScreen (Stack Navigator)
      • Settings (Screen)
      • Details (Screen)
  • BusinessApp
    • Orders (screen)

Even when following the tutorial and using the code defined there (as you can see from SettingsStackScreen) I am getting the following error printed over and over again. The BusinessApp works great, because it doesn't have Stack Navigators defined within it, only pure component screen.

 ERROR  Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator (created by SettingsStackScreen)
    in SettingsStackScreen (created by SceneView)

I tried creating the most minimal example possible, so I wasn't sure what else to change/try.

This is root stack navigator in App.js

  return (
    <NavigationContainer>
      <Stack.Navigator 
      initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} options={{ headerShown: false }} />
        <Stack.Screen name="Login" component={LoginScreen} options={{ title: t('Login-s') }}/>
        <Stack.Screen name="ConsumerApp" component={ConsumerAppScreen} options={{headerShown: false}}/>
        <Stack.Screen name="BusinessApp" component={BusinessAppScreen} options={{headerShown: false}}/>
      </Stack.Navigator>
    </NavigationContainer>
  );
}

The ConsumerAppScreen:

const Tab = createBottomTabNavigator();

export const ConsumerAppScreen = () => {
    const { t, i18n } = useTranslation();

    function DetailsScreen() {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Details!</Text>
            </View>
        );
    }

    function SettingsScreen({ navigation }) {
        return (
            <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                <Text>Settings screen</Text>
                <Button
                    title="Go to Details"
                    onPress={() => navigation.navigate('Details')}
                />
            </View>
        );
    }

    const SettingsStack = createNativeStackNavigator();

    function SettingsStackScreen() {
        return (
            <SettingsStack.Navigator>
                <SettingsStack.Screen name="Settings" component={SettingsScreen} />
                <SettingsStack.Screen name="Details" component={DetailsScreen} />
            </SettingsStack.Navigator>
        );
    }

    return (
        <Tab.Navigator
            initialRouteName="Settings"
            tabBar={(props) => <ConsumerTabBar {...props} />}
        >
            <Tab.Screen name="Settings" component={SettingsStackScreen} options={{ icon: require("../../assets/dashboard-icon.png"), title: t('Settings') }} />
        </Tab.Navigator>
    )
}

CodePudding user response:

It's because the way you created ConsumerAppScreen is not correct. Screen components and StackNavigator declarations shouldn't be inside a react component. (I think the tab bar should have more than one child, but I'm not sure about it.)

The correct implementation:


function DetailsScreen() {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Details!</Text>
        </View>
    );
}

function SettingsScreen({ navigation }) {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Settings screen</Text>
            <Button
                title="Go to Details"
                onPress={() => navigation.navigate('Details')}
            />
        </View>
    );
}

const SettingsStack = createNativeStackNavigator();

function SettingsStackScreen() {
    return (
        <SettingsStack.Navigator>
            <SettingsStack.Screen name="Settings" component={SettingsScreen} />
            <SettingsStack.Screen name="Details" component={DetailsScreen} />
        </SettingsStack.Navigator>
    );
}

// tab navigation
const Tab = createBottomTabNavigator();

export const ConsumerAppScreen = () => {
    const { t, i18n } = useTranslation();

    return (
        <Tab.Navigator
            initialRouteName="Settings"
            tabBar={(props) => <ConsumerTabBar {...props} />}
        >
            <Tab.Screen name="Settings" component={SettingsStackScreen} options={{ icon: require("../../assets/dashboard-icon.png"), title: t('Settings') }} />
        </Tab.Navigator>
    )
}

  • Related