reactjstypescriptfocustypeerroruse-ref

Cannot read properties of undefined (reading 'focus') on calling focus on useRef current object


Here I have to call useRef and have the focus method to be called on Ref object. Below is the Input.tsx component.

import React, { useRef, useState } from "react";

const Input = (props: any) => {

const [text, setText] = useState<string>('');

const inputRef = useRef<any>();

const onChangeHandler = (e) => {
  setText(e.target.value)
};

const submitHandler = (event: React.FormEvent) => {
event.preventDefault();
if (!text) {
    inputRef.current.focus();
  }

};  

return (
    <div>
<form onSubmit={submitHandler}>
  <label htmlFor="label">label</label>
  <input
    ref={inputRef}
    value={text}
    type="text"
    id="email"
    onChange={onChangeHandler}
    />
<button type="submit">Submit</button>
</form>
</div>


);

};

export default Input;

If I don't define the useRef type to be 'any' I'm getting compile error. Where as defining it 'any' I'm getting runtime error of cannot read properties of undefined (reading 'focus'). I think I'm not initializing any value on useRef that's why I'm getting this error. But I also know I can't assign string, number or boolean value and call focus() there. How can I fix this issue. I'm using typescript by the way.


Solution

  • I found the answer to my own question. The type of useRef.current for a text input field usually would be <HTMLInputElement | null> it cannot be undefined. Therefore this is how the code should be.

    import React, { useRef, useState } from "react";
    
    const Input = (props: any) => {
      const [text, setText] = useState<string>("");
    
      const inputRef = useRef<HTMLInputElement>(null); //made a change here
    
      const onChangeHandler = (e) => {
        setText(e.target.value);
      };
    
      const submitHandler = (event: React.FormEvent) => {
        event.preventDefault();
        if (!text) {
          inputRef.current!.focus(); //made a change here
        }
      };
    
      return (
        <div>
          <form onSubmit={submitHandler}>
            <label htmlFor="label">label</label>
            <input
              ref={inputRef}
              value={text}
              type="text"
              id="email"
              onChange={onChangeHandler}
            />
            <button type="submit">Submit</button>
          </form>
        </div>
      );
    };
    
    export default Input;
    

    Thanks to one of the comments below my question.