Skip to content

headerRight size and alignment is incorrect when rendered items change #2714

@elrony

Description

@elrony

Description

The size and position of the rendered headerRight are incorrect and do not update when the rendered items change.

Steps to reproduce

import {NavigationContainer} from '@react-navigation/native';
import {Pressable, Text, View, StyleSheet, Button} from 'react-native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {GestureHandlerRootView} from 'react-native-gesture-handler';

const styles = StyleSheet.create({
  button: {
    width: 42,
    height: 42,
    marginHorizontal: 5,
    padding: 5,
    borderRadius: 20,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'blue',
  },
  buttonsView: {
    flexDirection: 'row',
    borderWidth: 1,
  },
});

const Stack = createNativeStackNavigator();

function MyStack() {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: true,
        headerBackButtonDisplayMode: 'minimal',
      }}>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Profile" component={HomeScreen} />
    </Stack.Navigator>
  );
}

const HomeScreen = ({navigation}: any) => {
  const [secondButtonShown, setSecondButtonShown] = useState(true);
  const [thirdButtonShown, setThirdButtonShown] = useState(true);
  const [showAllButtons, setShowAllButtons] = useState(true);

  const headerRight = useCallback(() => {
    return (
      <>
        <Pressable style={styles.button} onPress={() => console.log(1)}>
          <Text>1</Text>
        </Pressable>
        {secondButtonShown && (
          <Pressable style={styles.button} onPress={() => console.log(2)}>
            <Text>2</Text>
          </Pressable>
        )}
        {thirdButtonShown && (
          <Pressable style={styles.button} onPress={() => console.log(3)}>
            <Text>3</Text>
          </Pressable>
        )}
      </>
    );
  }, [secondButtonShown, thirdButtonShown]);

  useLayoutEffect(() => {
    navigation.setOptions({
      headerStyle: {backgroundColor: 'pink'},
      headerRight: () => (
        <View
          style={[styles.buttonsView, !showAllButtons && {display: 'none'}]}>
          {headerRight()}
          <Pressable style={styles.button} onPress={() => console.log('D')}>
            <Text>[D]</Text>
          </Pressable>
        </View>
      ),
    });
  }, [navigation, headerRight, showAllButtons]);

  return (
    <View>
      <Text>Home Screen</Text>
      <Button
        title="Toggle 2nd button"
        onPress={() => setSecondButtonShown(p => !p)}
      />
      <Button
        title="Toggle 3rd button"
        onPress={() => setThirdButtonShown(p => !p)}
      />
      <Button
        title="Toggle All Right Buttons"
        onPress={() => setShowAllButtons(p => !p)}
      />
    </View>
  );
};

function App() {
  return (
    <GestureHandlerRootView>
      <NavigationContainer>
        <MyStack />
      </NavigationContainer>
    </GestureHandlerRootView>
  );
}

export default App;

Snack or a link to a repository

http://example.in.description

Screens version

4.7.0

React Native version

0.77.1

Platforms

Android

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

Android emulator

Device model

No response

Acknowledgements

Yes

Metadata

Metadata

Assignees

Labels

Missing reproThis issue need minimum repro scenarioPlatform: AndroidThis issue is specific to Android

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions