7

I'm just play around with typescript and I've got problem to use useRef in a custom element

passing it as prop

I've tried with

import React from "react";

export interface InputProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
    ref: HTMLElement | null
  }

const Input: React.FC<InputProps> = ({ ...inputProps }) => {
  return (
    <input
      className="px-2 py-1 text-gray-700 text-2xl bg-white border-2 border-gray-200 hover:border-purple-300 focus:outline-none focus:bg-white rounded-l-lg shadow-md"
      {...inputProps}
    />
  );
};
export default Input;


import React, { useRef } from "react";

import Input from "./input";
import Button from "./button";

const Form: React.FC = () => {
  const todoRef = useRef<HTMLElement | null>(null);
  return (
    <form onSubmit={}>
      <Input type="text" id="todo" ref={todoRef}/>
      <Button type="submit">+</Button>
    </form>
  );
};

export default Form;

What's the right way, please?

UPDATE

I worked out with: https://codesandbox.io/s/typescript-useref-example-e0hc4

3 Answers 3

3

You need to use React.forwardRef on the component you are passing the ref to, like so:

const Input = React.forwardRef<HTMLElement, InputProps>(({ ...inputProps }, ref) => {
  return (
    <input
      ref={ref}
      className="px-2 py-1 text-gray-700 text-2xl bg-white border-2 border-gray-200 hover:border-purple-300 focus:outline-none focus:bg-white rounded-l-lg shadow-md"
      {...inputProps}
    />
  );
});

Refs are treated differently than normal props. They are not included in the props object. To expose a ref inside a custom component you have to use forwardRef. Once the ref is exposed inside your component, you should assign it to one of the components in your return statement (usually the top level component, input in this case).


UPDATE:

If you're seeing the error React.HTMLElement is not assignable to type React.HTMLInputElement you should change the type of ref that you're creating to the appropriate one:

const todoRef = useRef<HTMLInputElement | null>(null)

and in the input component change the first line to:

const Input = React.forwardRef<HTMLInputElement, InputProps>(({ ...inputProps }, ref) => {
Sign up to request clarification or add additional context in comments.

3 Comments

Type 'Ref<HTMLElement>' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'. Type 'RefObject<HTMLElement>' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'. Type 'RefObject<HTMLElement>' is not assignable to type 'RefObject<HTMLInputElement>'.
I've got (JSX attribute) React.ClassAttributes<HTMLInputElement>.ref?: string | ((instance: HTMLInputElement | null) => void) | React.RefObject<HTMLInputElement> | null | undefined Type 'Ref<HTMLElement>' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'. Type 'RefObject<HTMLElement>' is not assignable to type 'string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null | undefined'. Type 'RefObject<HTMLElement>' is not assignable to type 'RefObject<HTMLInputElement>'.
Type it as an input element HTMLInputElement.
1

change to:

const Input: React.FC<InputProps> = React.forwardRef((inputProps, ref) => {  
return(  
    <input
      className="px-2 py-1 text-gray-700 text-2xl bg-white border-2 border-gray-200 hover:border-purple-300 focus:outline-none focus:bg-white rounded-l-lg shadow-md"
      ref={ref}      
      {...inputProps}
    />
)
})
export default Input;

output here: https://codesandbox.io/s/typescript-useref-example-p3hh4

6 Comments

Yes, I do there is this error const Input: React.FunctionComponent<InputProps> Type 'ForwardRefExoticComponent<Pick<InputProps, "accept" | "alt" | "autoComplete" | "autoFocus" | "capture" | "checked" | "crossOrigin" | "disabled" | "form" | "formAction" | "formEncType" | "formMethod" | ... 269 more ... | "onTransitionEndCapture"> & RefAttributes<...>>' is not assignable to type 'FunctionComponent<InputProps>'. Types of property 'defaultProps' are incompatible. Type 'Partial<Pick<InputProps, "accept" | "alt" | "autoComplete" | "autoFocus" | "capture" | "checked" |
This error in your code or my demo ? if in your code then need you make a simple codesandbox demo to review
It is in both :(
I can't see any error in demo, in my sample when click on button then focus move to input, just for test, and work as correctly
Put the mouse over row number 13 to see the error const Input: React.FC
|
-2

Try one of this:

  1. Use HTMLInputElement instead of HTMLElement
  2. <Input type="text" id="todo" ref={todoRef as any}/>
  3. Wrap the HTMLElement type into a ReactElement generic type

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.