Props in custom components React native + Typescript

9.6k Views Asked by At

I've got a problem with access to onChangeText in my custom component. Here is the code of my component:

import React from 'react';
import {TextInput, StyleSheet} from 'react-native';

type Props=
{
   style:any
   
}

const Input = (props:Props) =>
{
    return <TextInput {...props} style = {{...styles.input, ...props.style}} blurOnSubmit autoCorrect = {false} keyboardType = "number-pad" maxLength = {2} />
}

const styles = StyleSheet.create({
    
    input:{
        height:30,
        borderBottomColor: 'grey',
        borderBottomWidth: 1,
        marginVertical: 10
    }
        

})

export default Input;`

And here is the part of code in another file where i'm using it:

 <Input style = {styles.input} onChangeText = {numberInputHandler} value = {enteredValue} />

OnChangeText is underlined and the error is Property 'onChangeText' does not exist on type 'IntrinsicAttributes & Props'. I see in a tutorial that after typing {...props} in my custom component inside there is access to its props, but guy is writing in js and I'm in in ts. Thanks for help!

3

There are 3 best solutions below

0
On

You have to tell Typescript that in props there is a function called 'onChangeText', so you have to add it to your Props type:

type Props=
{
   style:any
   onChangeText: Function
}
1
On

Your Input component passes through all of its props to the underlying TextInput, so you probably want it to accept all of the props that the TextInput does. Right now it only accepts the prop style since that is the only property in Props.

The props that you want are exported from react-native as TextInputProps, so you can import that interface.

import { TextInput, TextInputProps, StyleSheet } from "react-native";

TextInputProps already includes a property style with a type that's much more accurate than your any, so you can delete your Props interface entirely.

const Input = (props: TextInputProps) => {

You'll now get an error when combining the two styles because props.style could be an array of styles. With react-native you can join multiple styles in an array, even when those styles could themselves be an array. So you can combine like this:

style={[styles.input, props.style]}

Since we allowed all of the TextInputProps,you won't get an error if you call your Input with <Input maxLength={5}/>. Right now, that maxLength prop would be ignored and overwritten by maxLength={2} because of the order -- later props override earlier ones. If that is what you want, then this component is fine:

const Input = (props: TextInputProps) => {
  return (
    <TextInput
      {...props}
      style={[styles.input, props.style ]}
      blurOnSubmit
      autoCorrect={false}
      keyboardType="number-pad"
      maxLength={2}
    />
  );
};

If you want custom props to override the default props, then you would want to change the order:

const Input = (props: TextInputProps) => {
  return (
    <TextInput
      blurOnSubmit
      autoCorrect={false}
      keyboardType="number-pad"
      maxLength={2}
      {...props}
      style={[styles.input, props.style]}
    />
  );
};
0
On

You can use custom props as well as TextInput Props in the combine, please refer to the code below,

import { TextInput, TextInputProps } from 'react-native';

interface OwnProps {
  style?: ViewStyle;
  password?: boolean;
  error?: string;
}

export type CustomInputProps = TextInputProps & OwnProps;

export const CustomInput = (props: CustomInputProps) => {
    const { style, password, error, ...restProps } = props;
    return (
      <TextInput
        secureTextEntry={password ? hidePassword : false}
        {...restProps}
      />
     );
}