Nativebase: Cannot focus Input component imperatively

Created on 20 Jul 2016  路  20Comments  路  Source: GeekyAnts/NativeBase

Given the sample code

        <InputGroup>
            <Icon name="ios-home" />
            <Input 
              ref={() => (console.log("onref"))}
            />
        </InputGroup>

the ref callback is never called (most likely due to cloning logic in InputGroup.

Additionally my guess is that I would be unable to call native focus method as it works for normal RN TextInput

Most helpful comment

@makeitnew @egiordano and others with the same problem using Item as floatingLabel.
After digging for a while the Item.js source code I ended up with this solution (I am using nativebase 2.0.12).

class Screen extends Component {
  (...)
  componentDidMount() {
    this.textInput._root.focus();
    this.textInput.props.onChangeText(this.props.inputValue);
  }
 (...)
  <Item floatingLabel>
    <Label>SomeLabel</Label>
    <Input
      getRef={(input) => { this.textInput = input; }}
      keyboardType="numeric"
      onChangeText={text => this.setState({ inputValue: text })}
      value={this.state.inputValue}
    />
  </Item>
 (...)
}

this.textInput.props.onChangeText(this.props.inputValue); is only needed if one wants to load the Input with a initial value.

All 20 comments

Yes, I am also having this issue. I am unable to call focus on an InputGroup Input with a ref.

Okay, thanks for bringing it to our attention. We'll look into it.

I have my version of a fix with these two pull requests:

117

Using React.cloneElement instead allows maintaining of the ref assigned to an Input (object references and string references both work using this patch)

118

Add a ref directly to the native TextInput. This allows you in your code to do something like this:

focusPasswordInput() {
    this._passwordInput._textInput.focus();
}

render() {
        return (
            <Container>
                <Content>
                    <InputGroup style={{marginBottom: 20}}>
                        <Icon name="ios-person" />
                        <Input
                            ref={c => this._usernameInput = c}
                            autoCapitalize="none"
                            autoCorrect={false}
                            placeholder="USERNAME"
                            onChangeText={(username) => this.setState({username})}
                            onSubmitEditing={() => this.focusPasswordInput()}
                            returnKeyType="next"
                            value={this.state.username}
                        />
                    </InputGroup>
                    <InputGroup style={{marginBottom: 10}}>
                        <Icon name="ios-unlock-outline" />
                        <Input
                            ref={c => this._passwordInput = c}
                            placeholder="PASSWORD"
                            secureTextEntry={true}
                            onChangeText={(password) => this.setState({password})}
                            returnKeyType="go"
                            value={this.state.password}
                        />
                    </InputGroup>
                </Content>
            </Container>
        )
    }

Fixed in 0.5.5 Thanks @pwoltman !

I'm in version 0.5.9 and a call to focus brings the "is not a function" error.
I'm setting a simple string ref (like "password") and calling "onSubmitEditing={() => this.refs.password.focus()}.
And getting a weird "_this2.refs.password.focus is not a function" error.

194 Please check this example

Perfect! Thank you!

why I can't use _textInput because undefined but I change like this it work.
change _textInput to _root

focusPasswordInput() {
    this._passwordInput._root.focus();
}

@oneatcoe What version of NativeBase are you running? Can you post the portion of your code where you are creating the main Input component and trying to reference the child TextInput?

In version 2.0.10 the ref property of Input is ignored if the Item has label is a floatingLabel or a stackedLabel.

Same problem here on 2.0.11

This working code are using this package.json:

"dependencies": {
"native-base": "^2.0.12",
"react": "~15.4.1",
"react-native": "0.42.0",
"react-native-responsive-image": "^2.0.2"
},

<Form style={{marginTop:20}}>
    <Item>
    <Icon active name='ios-at-outline' />
    <Input  
        ref='email' 
        placeholder='your email' 
       keyboardType='email-address' 
       returnKeyType='next' 
       autoCapitalize='none' 
       onSubmitEditing={()=>{this.refs.passwordField._root.focus();}}
        />
    </Item>
    <Item last>
        <Icon active name='ios-finger-print-outline' />
    <Input 
            ref='passwordField' 
            placeholder='your password' 
            returnKeyType='go' 
            secureTextEntry 
            autoCapitalize='none'
        />
    </Item>
</Form>

@makeitnew @egiordano and others with the same problem using Item as floatingLabel.
After digging for a while the Item.js source code I ended up with this solution (I am using nativebase 2.0.12).

class Screen extends Component {
  (...)
  componentDidMount() {
    this.textInput._root.focus();
    this.textInput.props.onChangeText(this.props.inputValue);
  }
 (...)
  <Item floatingLabel>
    <Label>SomeLabel</Label>
    <Input
      getRef={(input) => { this.textInput = input; }}
      keyboardType="numeric"
      onChangeText={text => this.setState({ inputValue: text })}
      value={this.state.inputValue}
    />
  </Item>
 (...)
}

this.textInput.props.onChangeText(this.props.inputValue); is only needed if one wants to load the Input with a initial value.

@franciscocpg - That finally worked! I have not found any reference to 'getRef' in the documentation and that should be fixed - this method seems to work the best.

More generic solution:

```export default class SignUpForm extends Component {

_focusInput(inputField) {
this[inputField]._root.focus();
}
render() {
return (


keyboardType='numeric'
returnKeyType='next'
getRef={(input) => this.mobileInput = input}
onSubmitEditing={() => this._focusInput('passwordInput')}
/>


secureTextEntry={true}
returnKeyType='next'
getRef={(input) => this.passwordInput = input}
onSubmitEditing={() => this._focusInput('emailInput')}
/>

...........

My solution is create Wrapper to style input inside. Keep input as native as posible.

const Wrapper = styled.div`
  width: 100%
  input {
    background-color: red;
  }
`;

class SearchInput extends React.Component {
  setFocus = () => {
     this.textInput.focus();
  }
  render() {
     return (
        <Wrapper>
            <button onClick={this.setFocus}>focus input</button>
            <input ref={el => { this.textInput = el; }} />
        </Wrapper>
     );
  }
}

So, using typescript with this reveals that this is a design flaw. _root doesn't exist on type Input. so typecsript won't let me access the focus() method

To avoid flow validating errors just use the following:

this.textInputRef && this.textInputRef._root.focus();

I have a similar need because
I want to give a focus in the <Input ... getRef={(input) => { this.textInput = input; }} after a click on the <Button>, but whenever I bind to a function and call a reference, for example:

setFocusInput(){
   this.textInput._root.focus();
}

return TypeError: undefined is not an object (evaluating 'this.textInput._root')

Someone could help with this situation?

Check Docs

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chetnadaffodil picture chetnadaffodil  路  3Comments

georgemickael-b picture georgemickael-b  路  3Comments

bsiddiqui picture bsiddiqui  路  3Comments

maphongba008 picture maphongba008  路  3Comments

natashache picture natashache  路  3Comments