Nata Vacheishvili
Nata Vacheishvili

Reputation: 497

How to create custom header options for each screen multi stack navigation react native?

I am looking for a way to set custom header options (styling, icons, enabling/disabling back button, left and right options for the header) for each of the screen in the stacks, while maintaining multi-stack architecture for my app in react native? This is how my App.js looks right now, and I am willing to change it if need be.

const Stack = createStackNavigator();
const App = () => {
  const ref = React.useRef();
  const { getInitialState } = useLinking(ref, {
    prefixes: ['FoodApp://'],
  });

  const AuthStack = createStackNavigator();

  function AuthStackScreen() {
    return (
      <AuthStack.Navigator>
        <AuthStack.Screen name="LogIn" component={LogIn} />
        <AuthStack.Screen name="SignUp" component={SignUp} />
      </AuthStack.Navigator>
    );
  }

  const AppStack = createStackNavigator();

  //I'd like to set different header options for each of the screen here
  function AppStackScreen() {
    return (
      <AppStack.Navigator>
        <AppStack.Screen name="MenuCategoryItems" component={MenuCategoryItems} />
        <AppStack.Screen name="Delivery" component={Delivery} />
        <AppStack.Screen name="Account" component={Account} />
        <AppStack.Screen name="Notification" component={Notification} />
        <AppStack.Screen name="Cart" component={Cart} />
      </AppStack.Navigator>
    );
  }

  //TODO: pass customized bar components
  const Tab = createBottomTabNavigator();

  //I'd like to set different header options for each of the screen here
  function Tabs(){
      return (
          <Tab.Navigator tabBar={props => <BottomMenu {...props} />}>
              <Tab.Screen name="Home" component={Home} />
              <Tab.Screen name="Delivery" component={Delivery} />
              <Tab.Screen name="Account" component={Account} />
              <Tab.Screen name="Notification" component={Notification} />
              <Tab.Screen name="Cart" component={Cart} />
          </Tab.Navigator>
      );
  }

  return (
      <NavigationContainer>
          <Stack.Navigator>
              <Stack.Screen name="Home" component={Tabs} />
              <Stack.Screen name="AppStack" component={AppStackScreen} />
              /*Should I place something else here so that I have access to both AppStack and Tabs navigations?*/
          </Stack.Navigator>
      </NavigationContainer>
  );
};

export default App;

Upvotes: 1

Views: 3594

Answers (2)

paul b.
paul b.

Reputation: 31

Not sure if this is what you need but here is how I customize some "borderColor" value for my header component.

You can pass any options you want via the setOptions method of the navigation component. It will be populated in the scene.descriptor.options parameter.

Below an example of how I am using it in my app.

the header options for my screen/navigator.

header: ({scene, previous, navigation}) => {
        const {options} = scene.descriptor;

        let borderColor = options.borderColor ?? 'yellow';

        if (scene.route.name.startsWith('Test')) {
             borderColor = 'blue';
        }

        return <HeaderBar options={options}
                          title={title}
                          previous={true}
                          navigation={navigation}
                          borderColor={borderColor}
        />;
    }

And in any of the screens components I can use

useLayoutEffect(() => {
    navigation.setOptions({
        borderColor: 'orange'
    })
}, [ navigation ])

Now, my <HeaderBar> component will receive a prop borderColor whose value is 'orange'.

export const HeaderBar = ({ options, title, previous, navigation, borderColor = 'yellow' }) => {
    [...]
    console.log(borderColor); // orange
}

As you can see, my HeaderBar component also receive the full options as a prop, therefore I could skip the borderColor prop and check the options inside the header component itself.

Like so

export const HeaderBar = ({ options, title, previous, navigation }) => {
    const { borderColor } = options;
    [...]
}

Hope it will help you if not too late.

Upvotes: 3

meowww
meowww

Reputation: 153

Well. You could hide header default of react-navigation in your stack.

function AppStackScreen() {
return (
  <AppStack.Navigator headerMode={'none'}>
    <AppStack.Screen name="MenuCategoryItems" component={MenuCategoryItems} />
    <AppStack.Screen name="Delivery" component={Delivery} />
    <AppStack.Screen name="Account" component={Account} />
    <AppStack.Screen name="Notification" component={Notification} />
    <AppStack.Screen name="Cart" component={Cart} />
  </AppStack.Navigator>

Then, you could custom header component and import it in each your screen. Sorry because my EL. hope help U.

Upvotes: 0

Related Questions