Forwarding refs by multiple levels [Typescript / React]

  javascript, reactjs, typescript

I’m trying to follow atomic design principles, but I’m not sure if I’m doing it correctly.
I have created three components: Form, ExpandableInput and Input. Input is HTML input wrapper, Expandable input is Input with dropdown and Form is just form. I want to access current input value from Form component so I’m doing ref forwarding by multiple levels. Everything works fine in Form component, but the problem is that I have to use ref.current.value in ExpandableInput component, but I’m getting following error.

Property ‘current’ does not exist on type ‘((instance:
HTMLInputElement | null) => void) | MutableRefObject<HTMLInputElement
| null>’. Property ‘current’ does not exist on type ‘(instance:
HTMLInputElement | null) => void’.

I don’t know how to tell typescript that ref variable in ExpandableInput has type of Ref and is not null. I don’t know if ref forwarding by multiple levels is good practice, maybe there is a better way to get input value.

Example code:
AddForm

const Form = () => {
    // Refs
    const caRef = useRef<HTMLInputElement>(null);

    return (
        <FormTemplate >
            <ExpandableInput
                option={CompetenceAreaOption}
                ref={caRef}

            />
        </FormTemplate>
    );
}

export default AddForm;

ExpandableInput

const ExpandableInput = React.forwardRef<HTMLInputElement, IProps>((
   props,
   ref
): JSX.Element => {

    const pickInputValue = (value: string): void => {
        console.log(ref.current) // Error
        console.log(ref) // Input reference
        }
    }

    return (
        <div>
            <div>
                <Input
                    ref={ref}
                />
            </div>             
        </div>
    );
})

export default ExpandableInput;      

Input

const Input = React.forwardRef<HTMLInputElement, IProps>(({
    props,
    ref
): JSX.Element => {
 
    return (
        <input
            ref={ref}
        />
    );
})


export default Input;

Source: Ask Javascript Questions

LEAVE A COMMENT