1

I followed the doc of the react-native-elements library but I get this.search as an undefined object...

searchbar react-native-elements

class SearchBarTest extends Component {

    componentDidMount()
    {
        this.search.focus()//search is undefined
    }
    render(){
        <SearchBar
          ref={search => this.search = search}
          ...
        />
    }

}

Any idea how to make this working?

EDIT:

Adding full context of the code.

The idea is having a component with a header and body. The header has an optional search bar or a title and two buttons depending on the props search.

If search props is true, then I display the searchBar.

PARENT COMPONENT:

import React, {Component} from 'react';
import {StyleSheet, View, Text, TouchableWithoutFeedback, Keyboard} from 'react-native';

import Icon from 'react-native-vector-icons/Ionicons';

import DismissableKeyboardContainer from '../../components/DismissableKeyboardContainer';

export default class Search extends Component {

    static navigationOptions = () => {
        return {
            tabBarIcon: ({tintColor}) => (
                <Icon name="ios-search-outline" size={25} color={tintColor}/>
            )
        }
    };

    render() {


        someMethod = () => {
            console.log('hello');
        }

        return (
            <DismissableKeyboardContainer search={true}>
                <View style={{flex: 1, alignItems: 'center'}}>
                    <Text>Hello world</Text>
                </View>

            </DismissableKeyboardContainer>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    }
});

COMPONENT where the actual searchBar component is used:

import React, { Component} from 'react';
import { Keyboard, TouchableWithoutFeedback, TouchableOpacity, View, Text, StyleSheet} from 'react-native';

import { SearchBar } from 'react-native-elements'

import Icon from 'react-native-vector-icons/Ionicons';

import PropTypes from 'prop-types';

class DismissableKeyboardContainer extends Component {

    static defaultProps = {
        title: '',
        search: false,
        buttonLeft: '',
        buttonRight: '',
        borderShadow: true,
        headerStyle:{}
    };

    componentDidMount()
    {

    }
    render() {

        let { title, search, buttonLeft, buttonRight, headerStyle, borderShadow } = this.props;

        return (        

            <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
                <View style={{ flex: 1 }}>
                    <View style={[styles.headerContainer, borderShadow ? styles.borderShadow : '', headerStyle]}>
                        {
                            !search && <View style={{position: 'absolute', padding: 10, bottom: 0, flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>

                                <TouchableOpacity style={{ flex: 0.2, alignItems: 'center'}}>

                                    {
                                        buttonLeft != "" && <Icon name={buttonLeft} size={25} color="grey" />
                                    }

                                </TouchableOpacity>

                                <View style={{ flex: 1, alignItems: 'center' }}>
                                    <Text style={styles.title}>{title}</Text>
                                </View>
                                <TouchableOpacity style={{ flex: 0.2, alignItems: 'center' }}>
                                    {
                                        buttonRight != "" && <Icon name={buttonRight} size={25} color="grey" />
                                    }
                                </TouchableOpacity>
                            </View>
                        }
                        {
                            search && <SearchBar
                                ref={search => this.search = search}
                                containerStyle={{ backgroundColor: 'transparent', borderTopWidth: 0, borderBottomWidth: 0 }}
                                inputStyle={{ backgroundColor: 'white' }}
                                lightTheme
                                onChangeText={someMethod}
                                placeholder='Type Here...'
                            />
                        }

                    </View>
                    <View style={{ flex: 1, backgroundColor: 'transparent'}}>

                        {this.props.children}

                    </View>
                </View>
            </TouchableWithoutFeedback>
        );
    }
}

const styles = StyleSheet.create({

    headerContainer: {
        flex: 0.12,
        justifyContent: 'flex-end',
        backgroundColor: 'white' ,
    },
    borderShadow: {
        borderColor: '#ddd',
        borderBottomWidth: 0,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.2,
        shadowRadius: 1,
        elevation: 1,
    },
    title: {
        fontSize: 18,
        fontWeight: 'bold'
    }
});

DismissableKeyboardContainer.propTypes = {
    title: PropTypes.string.isRequired,
    search: PropTypes.bool.isRequired,
    buttonLeft: PropTypes.string.isRequired,
    buttonRight: PropTypes.string.isRequired,
    headerStyle: PropTypes.any,
};

export default DismissableKeyboardContainer;
Vahid Boreiri
  • 3,418
  • 1
  • 19
  • 34
sbkl
  • 2,231
  • 2
  • 22
  • 28
  • Please give more information about your problem. Which library's `SearchBar` component are you using? – bennygenel Sep 23 '17 at 07:48
  • Sorry was in the title. Not in the body of the question. I talk about react-native-elements. Put the link above – sbkl Sep 23 '17 at 07:49
  • Your code looks fine to me. Is this an example code snippet or is it the exact code are you trying to use? – bennygenel Sep 23 '17 at 07:53
  • Exact same code... Read the React doc about ref as well and I can't see anything I'm doing wrong here... – sbkl Sep 23 '17 at 07:55
  • Can you please add the full error message? Maybe we are missing something and it can help. – bennygenel Sep 23 '17 at 07:57
  • Cannot read property 'focus' of undefined. Let me put the entire code and context in my question. But not sure it is relevant to solve this issue. – sbkl Sep 23 '17 at 07:59
  • are you sending `search={true}` hard-coded like this or getting the value from the state or something? – bennygenel Sep 23 '17 at 08:20
  • It's hardcoded. This is just an helper component. Let me try using the searchBar with a more simple example and see if I can make it work first. – sbkl Sep 23 '17 at 08:28
  • When I move the search bar to the parent component, the searchBar focus method works as expected... I would expect it should work the same way in a nested component... – sbkl Sep 24 '17 at 03:27

1 Answers1

1

I think I found the issue. As my SearchScreen is part of a TabBar from react-navigation, this.search.focus() error was appearing at the initial loading of the app. The Search screen being the second tab of the tabBar, I guess this is the reason why search couldn't be found as the screen was not active.

Found this answer: Trigger event on tabBar screen display

Which helped me to launch the this.search.focus() only when the screen Search is called under the componentDidUpdate() method

Please see code below:

1- First on my root navigator, I track react-navigation screen changes with onNavigationStateChange and screenProps

<Root 
    onNavigationStateChange={(prevState, currentState, action) => {
        let currentScreen = action.routeName;

        this.setState({ currentScreen })
    }}
    screenProps={{ currentScreen: this.state.currentScreen }}
/>

2- Then on my Parent component, I pass the currentScreen prop from I setup above in react-navigation

<DismissableKeyboardContainer search={true} currentScreen={this.props.screenProps.currentScreen}>
    <View style={{flex: 1, alignItems: 'center'}}>
        <Text>Hello world</Text>
    </View>

</DismissableKeyboardContainer>

3- Now, I'm checking the screen being displayed and launch this.search.focus() only if the screen Search is displayed inside my DismissableKeyboardContainer child component.

componentDidUpdate() {
    this.props.currentScreen === "Search" ? this.search.focus() : ''
}
sbkl
  • 2,231
  • 2
  • 22
  • 28