Skip to content

iOS: Header button reopens keyboard after search bar is dismissed #3677

@just1and0

Description

@just1and0

Description

When a screen has both a headerSearchBarOptions search bar and header buttons (e.g. headerRight), tapping a header button after dismissing the search bar keyboard causes the keyboard to reopen unexpectedly.

Video

Screen.Recording.2026-02-17.at.9.09.11.AM.mov

Steps to reproduce

  1. Use the code snippet below (screen with headerSearchBarOptions + headerRight button)
  2. Tap the search bar to focus it (keyboard opens)
  3. Dismiss the keyboard (tap Cancel or tap away)
  4. Tap the "Menu" button in the header
  5. Bug: The keyboard opens again instead of just triggering the button action

Snippet of code that reproduces the bug

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Alert, Button, ScrollView, Text, View } from 'react-native';

const Stack = createNativeStackNavigator();

function HomeScreen({ navigation }) {
  const [searchQuery, setSearchQuery] = React.useState('');

  React.useLayoutEffect(() => {
    navigation.setOptions({
      headerSearchBarOptions: {
        placement: 'stacked',
        hideWhenScrolling: false,
        onChangeText: (event) => setSearchQuery(event.nativeEvent.text),
      },
      headerRight: () => (
        <Button
          title="Menu"
          onPress={() => Alert.alert('Menu', 'Header button pressed')}
        />
      ),
    });
  }, [navigation]);

  return (
    <ScrollView contentInsetAdjustmentBehavior="automatic">
      <View style={{ padding: 20 }}>
        <Text style={{ fontSize: 16, lineHeight: 24 }}>
          1. Tap the search bar to focus it{'\n'}
          2. Dismiss the keyboard (tap Cancel){'\n'}
          3. Tap the "Menu" button in the header{'\n'}
          4. Bug: The keyboard opens again
        </Text>
      </View>
    </ScrollView>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Expected behavior

Tapping the header button after dismissing the search bar should only trigger the button's action, without reopening the keyboard.

Actual behavior

The keyboard reopens when tapping the header button.

Minimal reproducible example

https://github.com/sbkl/sdk-55-header-right-button-opening-keyboard

Also reported on Expo: expo/expo#43198

Root cause

  1. RNSScreenStackHeaderConfig.mm: updateViewController unconditionally reassigns navitem.searchController = searchBar.controller on every React re-render. UIKit interprets this as a new search controller being set and re-activates the search bar, which reopens the keyboard.
  2. RNSSearchBar.mm: searchBarCancelButtonClicked: calls resignFirstResponder on the RNSSearchBar wrapper but not on the actual UISearchBar (_controller.searchBar), so the native search bar may retain first responder status internally.

Fix

PR: #3676

Versions

  • react-native-screens: 4.23.0
  • react-native: 0.83.2
  • OS: iOS 26.2
  • Xcode: 26.2/17C52

Metadata

Metadata

Assignees

No one assigned

    Labels

    missing-infoThe user didn't precise the problem enoughmissing-reproThis issue need minimum repro scenario

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions