6

I'm building search page similar to Facebook or instagram. Basically if we press search button, it navigates to 'SearchScreen'. When its component is mounted, I want to set the search header is focused (cursor).

My problem is when I set TextInput ref as a prop. And I'm getting Stateless function components cannot have refs error. Is this right approach? Why is it not working? Do you know any better approach other than this?

I added _renderHeader private function to renderHeader props in FlatList. This is _renderHeader

  _renderHeader = () => {
    return (
      <View style={styles.layoutheader}>
        <View style={styles.containerheader}>
          <RkTextInput
            rkType='row'
            ref="sbar"  /////////////////////HERE////////////
            autoCapitalize='none'
            autoCorrect={false}
            label={<RkText rkType='awesome' style={{color:'white'}}>{FontAwesome.search}</RkText>}
            placeholder='Search'
            underlineWidth="1"
            underlineColor="white"
            style={styles.searchBarheader}
            inputStyle={{color:'white'}}
            labelStyle={{marginRight:0}}
            value={this.state.inputText}
            onChangeText={(inputText)=>{this.setState({inputText})}}
          />
          <View style={styles.left}>
            <RkButton
              rkType='clear'
              style={styles.menuheader}
              onPress={() => {
                this.props.navigation.goBack()
              }}>
              <RkText style={styles.titleText} rkType='awesome hero'>{FontAwesome.chevronLeft}</RkText>
            </RkButton>
          </View>
        </View>
      </View>
    )
  }

componentDidMount() {
    this.refs.sbar.focus(); ////////// Here I want to focus RkTextInput when it's loaded
}

UPDATE here is actual code as requested

class SearchScreen extends Component {
  static navigationOptions = ({navigation}) => ({
    header: null
  })

  state = {
    active: false,
    inputText: ''
  }
   ...
  _renderRow = (row) => {
    ...
    );
  }

  _renderHeader = () => {
    ...
  }

  render() {
    return (
      <FlatList
        data={null}
        renderItem={this._renderRow}
        renderHeader={this._renderHeader}
        keyExtractor={this._keyExtractor}
        ListHeaderComponent={this._renderHeader}
      />
    );
  }

  componentDidMount() {
    this.refs.sbar.focus();
  }
}
merry-go-round
  • 4,533
  • 10
  • 54
  • 102

2 Answers2

3

What seems to me is that you are not using the refs the right way. The way you are using them has been deprecated. You should follow this syntax:

<input
   type="text"
   ref={(input) => { this.textInput = input; }}
 />

and when you want to access it you can do this.textInput. In your case, this.textInput.focus().

slugo
  • 1,019
  • 2
  • 11
  • 22
Arslan Tariq
  • 2,478
  • 2
  • 22
  • 45
  • Could you elaborate it more? I need more explanation. It's awesome – merry-go-round Oct 17 '17 at 12:43
  • 1
    Actually, there is no problem with the context it's just that strings are deprecated for ref and this is how you do it now. For reference: https://reactjs.org/docs/refs-and-the-dom.html – Arslan Tariq Oct 17 '17 at 12:47
  • Um it only works with TextInput. Not RkTextInput. Weird – merry-go-round Oct 17 '17 at 12:55
  • I'm getting undefined is not a function this.textInput.focus() – merry-go-round Oct 17 '17 at 12:57
  • It should work with all DOM elements. Maybe RkTextInput does not support ref. For a workaround, what you can do is use the `inputStyle` prop. – Arslan Tariq Oct 17 '17 at 12:59
  • Actually RkTextInput is custom TextInput. It shouldn't work as React document says. How do we do that with inputStyle? – merry-go-round Oct 17 '17 at 13:02
  • THANKS THANKS I just found `autoFocus={true}` can set the TextInput is focused in `componentDidMount`. I didn't know I can do it with style – merry-go-round Oct 17 '17 at 13:05
  • 1
    https://akveo.github.io/react-native-ui-kitten/#/docs/ui-components/rktextinput Here under the props section, you can see that we can use `props` for `TextInput.props`. I guess now you get the idea. – Arslan Tariq Oct 17 '17 at 13:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/156921/discussion-between-arslan-tariq-and-john-baek). – Arslan Tariq Oct 17 '17 at 13:06
  • I know you know much about React Native and I want you to try this question! https://stackoverflow.com/questions/46864293/how-to-draw-square-to-tag-an-object-react-native – merry-go-round Oct 21 '17 at 14:51
  • 1
    From the React docs: You may not use the ref attribute on function components because they don’t have instances. ** To get around this simply add a useRef hook by importing: ```import React, {useRef} from "react";``` then to init: ```let typeAheadArrowDropdownRef = useRef(null);``` – Jason Rice Jul 11 '19 at 17:49
0

You're using RkTextInput which is a functional component and it cannot have a ref. That's why you can't focus it.

I don't see a way to focus the input other than wrapping the Component, getting the ref of the root and finding your input element in order to focus it. A rough example :

class RoughExample extends React.Component {
    componentDidMount() {
        //find the input from your root
        this.input = this.root.querySelector('input');
        //if it exists, focus
        this.input && this.input.focus();
    }
    render() {
        <div ref={ (node) => {this.root = node;} }>
            <RkTextInput />
        </div>
    }
}
Daniel Andrei
  • 2,654
  • 15
  • 16