React-native-paper: Unable to declare ref for TextInput

Created on 2 Sep 2019  ·  7Comments  ·  Source: callstack/react-native-paper

Environment

react-native-paper 3.0.0-alpha.3
react-native 0.59.8
Typescript 3.6.2

Description

I'm trying to convert my component that uses TextInput to typescript, but I'm getting an error at React.RefObject<TextInput>: 'TextInput' refers to a value, but is being used as a type here.ts(2749)

I tried yarn add https://github.com/callstack/react-native-paper.git to try to pull in #1218, but the command failed with this error:

✖ Errors found when building definition files.
example/src/index.native.tsx(1,25): error TS2307: Cannot find module 'expo'.
example/src/index.native.tsx(2,30): error TS2307: Cannot find module 'expo-keep-awake'.
example/src/index.native.tsx(18,39): error TS2307: Cannot find module 'react-navigation'.
example/src/RootNavigator.native.tsx(2,38): error TS2307: Cannot find module 'react-navigation'.

bob build

build files for publishing

Options:
  --help     Show help                                                 [boolean]
  --version  Show version number                                       [boolean]

Error: Failed to build definition files.
    at build (/Users/frank/Library/Caches/Yarn/v4/.tmp/37678653438a710e932e2eb30c14dbbe.d644354d396ad8e765c85886ab3033b45f7a7c00.prepare/node_modules/@react-native-community/bob/lib/targets/typescript.js:63:11)
    at <anonymous>
error Command failed with exit code 1.

Reproducible Demo

import React from 'react';
import { TextInput } from 'react-native-paper';
class MyScreen extends React.Component<any, any> { 
    private input: React.RefObject<TextInput> = React.createRef();
    render() {
        return <TextInput ref={this.input} ... />
    }
    onSubmit() {
        this.input.current.focus()
    }
}

Am I doing this right? I know the ref spec in general went through a few iterations. Great library by the way, beautiful components. 👍

Stale

Most helpful comment

Per the lines here: https://github.com/callstack/react-native-paper/blob/efe17beafcc3bd83f4d84971499bd85647df9c84/src/components/TextInput/TextInput.tsx#L21-L23

I think you just need to use the react-native TextInput type for your ref, rather than trying to use the react-native-paper version.

Based on @savagematt's example, I'd try:

import React, { Component, createRef } from 'react';
import { TextInput as RNTextInput } from 'react-native';
import { TextInput } from 'react-native-paper';

export class Example extends Component {
  private firstInput = createRef<RNTextInput>();

  componentDidMount(): void {
    this.firstInput.current?.focus();
  }

  render() {
    return <TextInput
      ref={this.firstInput}
    />

  }
}

I haven't tested the above though. I'm using function components as seen here: https://github.com/callstack/react-native-paper/issues/1453#issuecomment-699163546

All 7 comments

@francisco-mercury maybe this example will help you with the ref prop 👍 The first input focuses the second one on submit :

 <TextInput
mode="outlined"
label="email"
dense
autoComplete="email"
keyboardType="email-address"
autoCapitalize="none"
onChangeText={email => this.setState({ email })}
value={this.state.email}
returnKeyType="next"
onSubmitEditing={() => {
this.passwordInput.focus();
}}
blurOnSubmit={false}
/>
<TextInput
mode="outlined"
dense
label="password"
secureTextEntry
autoComplete="password"
onChangeText={password => this.setState({ password })}
value={this.state.password}
onSubmitEditing={this.onPress}
returnKeyType="done"
ref={input => {
this.passwordInput = input;
}}
/>          

I solve this issue:

'TextInput' refers to a value, but is being used as a type here.ts(2749)

by this:

import React from 'react';
import { TextInput } from 'react-native-paper';

class MyScreen extends React.Component<any, any> { 
  private input!: typeof TextInput;

  render() {
    const refProps: any = {
      ref: (input: any) => (this.input = input)
     };
    return <TextInput {...refProps} ... />
  }

Something changes in v. 3.0.0 that broken type declrations. In v 2.16 declaration was input: TextInput. Now it is input: typeof TextInput

Hello 👋, this issue has been open for more than 2 months with no activity on it. If the issue is still present in the latest version, please leave a comment within 7 days to keep it open, otherwise it will be closed automatically. If you found a solution on workaround for the issue, please comment here for others to find. If this issue is critical for you, please consider sending a pull request to fix the issue.

This is still an issue at v 3.3.0

import * as React from "react";
import {createRef} from "react";
import {TextInput} from "react-native-paper";

export class Example extends React.Component {
  // TS2749: TextInput refers to a value but is being used as a type here
  private firstInput = createRef<TextInput>();

  componentDidMount(): void {
    this.firstInput.current.focus();
  }

  render() {
    return <TextInput
      ref={this.firstInput}
    />

  }
}

The issue is that the class is not exported.

I think fixing it would be as simple as adding export to the beginning of this line(?):
https://github.com/callstack/react-native-paper/blob/master/src/components/TextInput/TextInput.tsx#L166

But I haven't yet understood this commit, which is I think where the issue was introduced?:
https://github.com/callstack/react-native-paper/commit/6143dd505307c3bf75372b86c30cf40cdc8c2c6a

Maybe @pbitkowski can say more? I think preventing referring to TextInput as a type might be intentional?

But I can't figure out the generics gubbins I need to do to refer to a type that includes the focus() method.

Sorry I can't be more help. Run out of time to diagnose.

As an unsatisfying workaround, I've just done createRef<any>() rather than createRef<TextInput>()

Has react native removed the ref attribute for TextInput? It's no longer in the docs

Per the lines here: https://github.com/callstack/react-native-paper/blob/efe17beafcc3bd83f4d84971499bd85647df9c84/src/components/TextInput/TextInput.tsx#L21-L23

I think you just need to use the react-native TextInput type for your ref, rather than trying to use the react-native-paper version.

Based on @savagematt's example, I'd try:

import React, { Component, createRef } from 'react';
import { TextInput as RNTextInput } from 'react-native';
import { TextInput } from 'react-native-paper';

export class Example extends Component {
  private firstInput = createRef<RNTextInput>();

  componentDidMount(): void {
    this.firstInput.current?.focus();
  }

  render() {
    return <TextInput
      ref={this.firstInput}
    />

  }
}

I haven't tested the above though. I'm using function components as seen here: https://github.com/callstack/react-native-paper/issues/1453#issuecomment-699163546

Was this page helpful?
0 / 5 - 0 ratings