Skip to content
Advertisement

How to create a reusable Input component with React & TypeScript?

It’s my first attempt with React TypeScript and don’t fully understand the error I’m getting when trying to build a reusable Input component. What is the TypeScript way of approaching this kind of component?

See Component & Error below:

import React, { FC, InputHTMLAttributes } from 'react';

interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
    name: string;
    label: string;
    ref: string;
}

const Input: FC<InputProps> = ({ name, label, ...otherProps }, ref) => {
    return (
        <label className={styles.formLabel}>
            {label}
            <input
                className={styles.formInput}
                {...otherProps}
                name={name}
                ref={ref}
            />
        </label>
    );
};

const FormInput = React.forwardRef(Input);

export default FormInput;

Error

TypeScript error in /Users/Timmchoover/Documents/Projects/evaly/evaly-app/src/before-login/components/forms/form-input/form-input.component.tsx(25,36):
Argument of type 'FC<InputProps>' is not assignable to parameter of type 'ForwardRefRenderFunction<unknown, InputProps>'.
  Types of property 'defaultProps' are incompatible.
    Type 'Partial<InputProps> | undefined' is not assignable to type 'undefined'.
      Type 'Partial<InputProps>' is not assignable to type 'undefined'.  TS2345

    23 | };
    24 | 
  > 25 | const FormInput = React.forwardRef(Input);
       |                                    ^
    26 | 
    27 | export default FormInput;
    28 |

Advertisement

Answer

I don’t think FC is satisfying the type constraint here, try ForwardRefRenderFunction instead:

import React, { ForwardRefRenderFunction, InputHTMLAttributes } from 'react';

interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
    name: string;
    label: string;
    ref: string;
}

const Input: ForwardRefRenderFunction<HTMLInputElement, InputProps> = ({ name, label, ...otherProps }, ref) => {
    return (
        <label className={styles.formLabel}>
            {label}
            <input
                className={styles.formInput}
                {...otherProps}
                name={name}
                ref={ref}
            />
        </label>
    );
};

const FormInput = React.forwardRef(Input);

export default FormInput;

Alternatively, you can combine Input and FormInput into one and let TypeScript infer for you:

const FormInput = React.forwardRef<HTMLInputElement, InputProps>(({ name, label, ...otherProps }, ref) => {
    ...
});


export default FormInput;
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement