Home > Software engineering >  Navigating in BottomTabBar within nested Stack Navigator causes more renders than previous
Navigating in BottomTabBar within nested Stack Navigator causes more renders than previous

Time:12-11

I have a bottom tab bar, with a screen that I need to be 'hidden' from the tabs (e.g. no tab shown). So I created a Native Stack and have the initial screen of that stack set to the bottom tab stack. However - when I navigate using the bottom tabs, I get this error:

Error: Rendered more hooks than during the previous render.

This error is located at:
    in BottomTabView (created by BottomTabNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by BottomTabNavigator)
    in BottomTabNavigator (created by BottomTabs)
    in BottomTabs (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SceneView)
    in RCTView (created by View)
    in View (created by DebugContainer)
    in DebugContainer (created by MaybeNestedStack)
    in MaybeNestedStack (created by SceneView)
    in RCTView (created by View)
    in View (created by SceneView)
    in RNSScreen (created by AnimatedComponent)
    in AnimatedComponent
    in AnimatedComponentWrapper (created by InnerScreen)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by InnerScreen)
    in InnerScreen (created by Screen)
    in Screen (created by SceneView)
    in SceneView (created by NativeStackViewInner)
    in Suspender (created by Freeze)
    in Suspense (created by Freeze)
    in Freeze (created by DelayedFreeze)
    in DelayedFreeze (created by ScreenStack)
    in RNSScreenStack (created by ScreenStack)
    in ScreenStack (created by NativeStackViewInner)
    in NativeStackViewInner (created by NativeStackView)
    in RCTView (created by View)
    in View (created by SafeAreaInsetsContext)
    in SafeAreaProviderCompat (created by NativeStackView)
    in NativeStackView (created by NativeStackNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by NativeStackNavigator)
    in NativeStackNavigator (created by MainStack)
    in MainStack (created by App)
    in RNCSafeAreaView (created by App)
    in $29383e587d62412a$export$9f8ac96af4b1b2ae (created by NativeBaseProvider)
    in ToastProvider (created by NativeBaseProvider)
    in PortalProvider (created by NativeBaseProvider)
    in HybridProvider (created by NativeBaseProvider)
    in ResponsiveQueryProvider (created by NativeBaseProvider)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by NativeBaseProvider)
    in NativeBaseConfigProviderProvider (created by NativeBaseProvider)
    in NativeBaseProvider (created by App)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by App)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by App)
    in App
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in promptdrinksMobile(RootComponent), js engine: hermes

I'm not seeing anything really helpful to troubleshoot. If I take the bottom tab nav out of the nested navigator, it works perfectly. Here is my setup:

The Main Stack:

import { createNativeStackNavigator } from '@react-navigation/native-stack'

// Stack imports
import BottomTabs from './BottomTabNavigator'

// Screen imports
import DetailScreen from '../screens/DetailScreen'

const Stack = createNativeStackNavigator()

const MainStack = () => {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}
    >
      <Stack.Screen name="BottomTabNavigator" component={BottomTabs} />
      <Stack.Screen name="DetailPage" component={DetailScreen} />
    </Stack.Navigator>
  )
}

export default MainStack

The Bottom Tab Stack:

import React from 'react'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'

// Config imports
import { siteVars } from '../config/siteConfig'

// Component imports
import TabItem from '../components/tab_bar/TabItem'

// Screen imports
import Home from '../screens/Home'
import Generated from '../screens/Generated'
import Settings from '../screens/Settings'

// Components
import Header from '../components/layout/Header'

// Stores

const Tab = createBottomTabNavigator()

const BottomTabs = () => {
  return (
    <Tab.Navigator
    initialRouteName={siteVars.generatedName}
      sceneContainerStyle={{flexGrow: 1}}
      screenOptions={{
        header: Header,
        tabBarShowLabel: false,
        tabBarStyle: {
          height: 20,
          paddingTop: 30,
          paddingBottom: 35
        }
      }}
    >
      <Tab.Screen 
        name="Home" 
        component={Home}
        options={{
          tabBarIcon: (props) => <TabItem {...props} alt="Home icon" name="Home" logo={require('../assets/logos/home.png')} />
        }}
      />
      <Tab.Screen 
        name={siteVars.generatedName} 
        component={Generated} 
        options={{
          tabBarIcon: (props) => <TabItem {...props} alt="Generated Icon" name={siteVars.generatedName} logo={require('../assets/logos/generated_logo.png')} />
        }}
      />
      <Tab.Screen
        name={"Settings"}
        component={Settings}
        options={{
          tabBarIcon: (props) => <TabItem {...props} alt="Generated Icon" name={"Settings"} logo={require('../assets/logos/settings.png')} />
        }}
      />
    </Tab.Navigator>
  )
}

export default BottomTabs

My App file:

/**
 *
 * Generated with the TypeScript template
 * https://github.com/react-native-community/react-native-template-typescript
 *
 * @format
 */

import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { Modal, NativeBaseProvider, StatusBar } from 'native-base'
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'

// Tabs and Navigators
import BottomTabs from './src/navigators/BottomTabNavigator'
import MainStack from './src/navigators/MainStackNavigator'

// Styles and Themes
import theme from './src/styles/theme'

const App = () => {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <NativeBaseProvider theme={theme}>
            <SafeAreaView edges={['top', 'right', 'left']} style={{flexGrow: 1, backgroundColor: '#333'}}>
              <StatusBar barStyle="light-content" />
                <MainStack />
            </SafeAreaView>
        </NativeBaseProvider>
      </NavigationContainer>
    </SafeAreaProvider>
  )
}

export default App;

CodePudding user response:

It's not causing more renders than previous, it's saying it renders more hooks then previous - which can happen when you're trying to use hooks where it cannot be used, like a render callback.

From the code you posted, this looks like the culprit:

header: Header,

The header option takes a callback function, not a component. So it needs to be:

header: (props) => <Header {...props} />,
  • Related