Denis Kulagin
Denis Kulagin

Reputation: 8947

How to implement an application-wide search bar?

It seems to be a pretty common task to have an application-wide search bar in the header. Unfortunately, I haven't found some ready recipes on how to accomplish it the right way. My solution was to place a custom SearchBox component in the React Native Navigation header using headerTitle:

static navigationOptions = ({navigation}) => {
     headerTitle: () => (<SearchBox ... />)

It had its drawbacks, e.g. using "static" variables to pass state and behavior between the application and the component. But it worked so far. Now, after moving to RNN 4.1.1, it stopped working because of the specifics of how the header is implemented in the RNN:

enter image description here

TextInput now doesn't fill the header's width and doesn't handle the text input properly.

enter image description here

I am looking for a way to implement an application-wide search bar in RN, that features the following properties:

Update

Ideally, I am looking for an answer that features the following aspects:

Upvotes: 7

Views: 1279

Answers (1)

MBach
MBach

Reputation: 1645

You are almost done, but unfortunately, I think this is not possible with react-navigation 4. In latest, 5.0 which is now production-ready, you have to rewrite your stacks.

In 5.0, you can use the useFocusEffect which is nice to detect Back Actions. So, you have your header like this:

function SearchBar(props) {
  return (
    <TextInput />
  );
}

function StackScreen() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ headerTitle: props => <SearchBar {...props} /> }}
      />
    </Stack.Navigator>
  );
}

The problem is, you have to repeat options and useFocusEffect logic on every screen.

Another approach could be:

  1. Disable all headers globally
  2. In all your screens, create a layout like this:
      <View style={{ flex: 1 }}>
        <MyAppbarHeader title={'PageA'} resetOnBack={false/true} />
        <View style={{ flex: 1, margin: 8 }}>
          <FlatList
            data={someDataOnMyScreen}
            renderItem={renderItem}
          />
        </View>
      </View>

In MyAppbarHeader you can pass the title as props, and other props like resetOnBack and implement the logic in this functional component.

Upvotes: 4

Related Questions