NativeBase: Input Component doesn't support React useRef Hook

Issue Description

Environment:

  • React Native v0.59.9
  • NativBase v2.12.1
  • Xcode v10.2.1 (10E1001)

Expected behaviour

Using useRef hook from React, one can get a handle on a field to execute focus(). As per React’s Docs - https://reactjs.org/docs/hooks-reference.html#useref

Example:

import React, { useRef } from 'react'

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

Actual behaviour

When attempting the above logic on a NativeBase input field, an error is returned:

null is not an object (evaluating ‘inputEl.current.focus’)

Steps to reproduce

import React, { useRef } from 'react'
import { Form, Item, Label, Input, Button, Icon, Text } from 'native-base'
import { View } from 'react-native'

export default function TestFocus () {
  const testRef = useRef(null)

  function handleFocus () {
    testRef.current.focus()
  }

  return (
    <View >
      <Form>
        <Item floatingLabel>
          <Label>Focus Field</Label>
          <Input
            ref={testRef}
            onChangeText={handleFocus}
          />
        </Item>
        <Button success iconLeft onPress={handleFocus}>
          <Icon name='checkmark-circle-outline' />
          <Text>Test Focus</Text>
        </Button>
      </Form>
    </View>
  )
}
image

Is the bug present in both iOS and Android or in any one of them?

Only tested with iOS but most likely with Android as well

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 8
  • Comments: 15 (1 by maintainers)

Most upvoted comments

Hi @agilitehub , update to latest Native-base v2.13.14 . Let us know if the issue still persists. Closing for now.

const inputEl = useRef(null);

const onButtonClick = () => {
    inputEl.current._root.focus();
  };
<Item>
     <Label>Username</Label>
     <Input ref={inputEl} onChangeText={onButtonClick} />
</Item>
<Button onPress={onButtonClick}>
    <Text>Button to focus on Input</Text>
</Button>

I had to use React.useState() instead.

function SignInScreen() {
    const [passwordInputRef, setPasswordInputRef] = React.useState(null)

    return (
        <Form>
            <Item floatingLabel>
            <Label>Email</Label>
            <Input
                onSubmitEditing={() => {
                    passwordInputRef._root.focus()
                }}
            />
            </Item>
            <Item floatingLabel>
            <Label>Password</Label>
            <Input
                getRef={(c) => setPasswordInputRef(c)}
            />
            </Item>
        </Form> 
    )
}

export default SignInScreen

Using useRef() is still not working in version 2.15.2. I’ve tried the solution outlined by @hanykumar and it didn’t work for me either. current gets never set.

I had to use React.useState() instead.

function SignInScreen() {
    const [passwordInputRef, setPasswordInputRef] = React.useState(null)

    return (
        <Form>
            <Item floatingLabel>
            <Label>Email</Label>
            <Input
                onSubmitEditing={() => {
                    passwordInputRef._root.focus()
                }}
            />
            </Item>
            <Item floatingLabel>
            <Label>Password</Label>
            <Input
                getRef={(c) => setPasswordInputRef(c)}
            />
            </Item>
        </Form> 
    )
}

export default SignInScreen

this worked for me except I had to use ref instead of getRef

As per Native Base documentation, you have to use a function for the ref property instead of a variable (see https://docs.nativebase.io/Components.html#ref-components-headref). But the c variable in that example is not compatible with MutableRefObject<any> type of the value returned by useRef hook. So, instead of current property, it has a _root property. The bottom line is if you’re not using TypeScript the example in the docs should work perfectly fine:

let inputElement = useRef(null);

useEffect((): void => {
    inputElement._root.focus();
});

...

<Input
  ref={(input): void => {
    inputElement = input;
  }}
/>

So the actual request here from my perspective is to make input compatible with MutableRefObject<any>

same issue here

@mzu Did you get any solution for the same?