umhan35 / react-native-search-bar

The high-quality iOS native search bar for react native.
MIT License
867 stars 209 forks source link

SearchBar actions trigger TabBarIOS.Item onPress #124

Closed allardvanderouw closed 7 years ago

allardvanderouw commented 7 years ago

The SearchBar actions (cancel/search) triggers the TabBarIOS.Item onPress. This will cause unexpected behavior if other code is attached to the onPress.

Please see the code below to reproduce the issue. The console.warn('selectTabBarItem') is triggered when changing tabs (as expected) but also on the contacts tab when searching on a value or when pressing cancel on the search bar.

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { ScrollView, TabBarIOS, Text } from 'react-native'
import SearchBar from 'react-native-search-bar'

class MyTabBarIOS extends PureComponent {
  state = {
    tabName: 'bookmarks'
  }

  selectTabBarItem = (tabName) => {
    console.warn('selectTabBarItem')
    this.setState({ tabName })
  }

  render = () => (
    <TabBarIOS>
      <TabBarIOS.Item
        systemIcon='bookmarks'
        selected={ this.state.tabName === 'bookmarks' }
        onPress={() => this.selectTabBarItem('bookmarks')}>
        <ScrollView>
          <Text>Bookmarks</Text>
        </ScrollView>
      </TabBarIOS.Item>
      <TabBarIOS.Item
        systemIcon='contacts'
        selected={ this.state.tabName === 'contacts' }
        onPress={() => this.selectTabBarItem('contacts')}>
        <ScrollView>
          <SearchBar showsCancelButton={true} />
        </ScrollView>
      </TabBarIOS.Item>
      <TabBarIOS.Item
        systemIcon='downloads'
        selected={ this.state.tabName === 'downloads' }
        onPress={() => this.selectTabBarItem('downloads')}>
        <ScrollView>
          <Text>Downloads</Text>
        </ScrollView>
      </TabBarIOS.Item>
    </TabBarIOS>
  )
}

Any idea why this is happening?

allardvanderouw commented 7 years ago

I fixed it by replacing the onPress function. The onSearchButtonPress and onCancelButtonPress functions of SearchBar do not stop the onPress event propagation. This is causing the event to proceed up to the app chain and also trigger the onPress of the TabBarIOS.Item.

See the onPress function below for my resolution.

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import SearchBar from 'react-native-search-bar'

class ListSearchBar extends PureComponent {
    static propTypes = {
        placeholder: PropTypes.string.isRequired,
        search: PropTypes.func.isRequired,
    }

    state = {
        hasFocus: false
    }

    handleSearchBarOnFocus = () => {
        this.setState({ hasFocus: true })
    }

    unFocus = () => {
        this.searchBar.unFocus()
        this.setState({ hasFocus: false })
    }

    handleSearchBarOnPress = (event) => {
        event.stopPropagation()
        const button = event.nativeEvent.button
        const searchText = event.nativeEvent.searchText

        if (button === 'search') this.props.search(searchText)
        if (button === 'cancel') this.props.search(null)

        this.unFocus()
    }

    render = () => (
        <SearchBar
            onFocus={this.handleSearchBarOnFocus}
            onPress={this.handleSearchBarOnPress}
            placeholder={this.props.placeholder}
            ref={(searchBar) => this.searchBar = searchBar}
            showsCancelButton={this.state.hasFocus}
        />
    )
}

export default ListSearchBar