React-native-screens: Setting `headerLeft` on Android modal hides title

Created on 12 Sep 2020  路  10Comments  路  Source: software-mansion/react-native-screens

Greetings!
Either I've found a bug (and have failed to find a solution online), or my complete lack of understanding which, if the latter, I will retire into the hills of Saskatchewan, should I ever find one.

When presenting a screen modally inside a native Stack Navigator - _on android_ - via presentationStyle: modal, everything works as one would expect. However, when I specify a headerLeft in the navigation options of the target screen, the title mysteriously disappears.

Sample project can be found here: https://github.com/beardwin/AndroidRNScreensBug

Expo 38.0.8

react-native-screens 2.9.0.

The app is basically as follows:

import React, { useEffect } from "react";
import { StackScreenProps } from "@react-navigation/stack";
import { createNativeStackNavigator } from "react-native-screens/native-stack";
import { Button, StyleSheet, Text, View } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { enableScreens } from "react-native-screens";

enableScreens();

type NavigatorParams = {
  Home: undefined;
  PooFarts: undefined;
};

const HomeScreen = ({
  navigation,
}: StackScreenProps<NavigatorParams, "Home">) => (
  <View style={styles.screen}>
    <Text>Home Screen</Text>
    <Button
      onPress={() => {
        navigation.navigate("PooFarts");
      }}
      title="Pop a poo fart"
    />
  </View>
);

const PooFartsScreen = ({
  navigation,
}: StackScreenProps<NavigatorParams, "PooFarts">) => {
  useEffect(() => {
    navigation.setOptions({
      title: "Fiddlesticks",
      // uncomment below, and the title will no longer appear
      // headerLeft: () => <Button title="Adios!" onPress={navigation.goBack} />,
    });
  }, [navigation]);

  return (
    <View style={styles.screen}>
      <Text>Poo Farts</Text>
    </View>
  );
};

const Stack = createNativeStackNavigator<NavigatorParams>();

const Navigator = () => (
  <Stack.Navigator>
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen
      name="PooFarts"
      component={PooFartsScreen}
      options={{ stackPresentation: "modal" }}
    />
  </Stack.Navigator>
);
export default function App() {
  return (
    <NavigationContainer>
      <Navigator />
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  screen: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: "center",
    alignItems: "center",
  },
});

On Android

All 10 comments

I don't think it has something to do with the modal presentation. The title disappears because it is replaced with the button and it is how it works on Android and is mentioned here: https://github.com/software-mansion/react-native-screens/tree/master/native-stack#headerleft. Can I help you more with this?

Thanks for this! Man.... I don't know how many times I read the docs and somehow.... missed that. The documentation says "For now, on Android..." - does that mean this is an issue in Android, or RNS, or is this just the way it is for android?

I thought maybe there is a way to do have both left items and title, but couldn't find any solution, so probably it is not possible. If you find any a way to do it, please post it here. Can I help you more with that?

Sounds good dude - if I find anything I'll let you know. Other than that, I'm good! Thanks for all your help!

I am closing this issue then. Comment here if you find anything and good luck on the journey to the hills of Saskatchewan.

hahaha - well played, good sir, well played. Back to the homelands I go!

@beardwin Running into the same issue now, did you find a solution?

@JoniVR - no solution. As per Wojciech's comment:

he title disappears because it is replaced with the button and it is how it works on Android and is mentioned here: https://github.com/software-mansion/react-native-screens/tree/master/native-stack#headerleft.

There's a couple things that can be done. creating platform specific headers/navigators for that specific flow, or....

do what i did, which is say "don't worry about android for now." I'm ultimately re-working the nav flow for this specific use case because I think it'll be more delightful.

Alright, the reason why it's happening makes sense, it's just that the title could probably be a separate property or something.. Thanks for the speedy reply! I think I'll just go ahead and try to replicate the original title and add a button next to it similarly to how it looks inside modals.

Hi @beardwin, I ran into the same issue and solved it as follows, by using the headerCenter option and a helper method to create navigation options that can easily be reused. Trick is to set the title empty for Android and use the headerCenter option instead. For iOS the functionality can be kept as-is.

const stackNavigatorOptions = (title: string): NativeStackNavigationOptions => {
  const options: NativeStackNavigationOptions = {
    headerBackTitleStyle: {
      fontSize: 16
    },
    title: Platform.OS === 'android' ? '' : title,
    headerTitleStyle: {
      fontSize: 16,
    },
  };

  if (Platform.OS === 'android') {
    options.headerCenter = () =>  <Text>{title}</Text>;
  }

  return options;
};

Then you can use this method in your navigators like this:

<Stack.Screen
  name="SomeScreen"
  component={SomeScreenComponent}
  options={{
    ...stackNavigatorOptions('Title of the screen'),
  }}
/>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

OmarBasem picture OmarBasem  路  4Comments

ukasiu picture ukasiu  路  4Comments

jeveloper picture jeveloper  路  5Comments

chai86 picture chai86  路  3Comments

sibelius picture sibelius  路  3Comments