Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to type a input ref for file upload

I'm trying to type the ref for the input, but not sure how. I'm using it for file upload. Any idea on how I can type this?

const ProfileLayout: React.FC = ({ children }) => {

  let inputUpdateAvatarPhoto = useRef();

.
.
.
.

 const handleImageChange = async (e: any) => {
   const formData = new FormData();
        
   formData.append('avatar', inputUpdateAvatarPhoto.files[0]);
    
.
.
.
.

    <input
      id="avatar"
      accept="image/*"
      type="file"
      ref={input => (inputUpdateAvatarPhoto = input)}
      onInput={e => {
      handleImageChange(e);
      }}
    />

enter image description here

enter image description here

like image 901
jarwin Avatar asked Jun 11 '26 22:06

jarwin


1 Answers

Fixing Your Ref

Your ref has a number of issues:

  • You need to declare the type of your ref by setting the generic on useRef like useRef<HTMLInputElement>.
  • React expects the initial value for a DOM element ref to be null instead of undefined.
  • You are mixing up ref object syntax with callback ref syntax. With a ref object you just pass the whole object to the DOM element like ref={inputUpdateAvatarPhoto}
  • In order to access the current value of the ref object, you need to look at the .current property

This code should work, but the next code is better

const ProfileLayoutV1: React.FC = ({ children }) => {
  const inputUpdateAvatarPhoto = useRef<HTMLInputElement>(null);

  const handleImageChange = async (e: React.FormEvent<HTMLInputElement>) => {
    const files = inputUpdateAvatarPhoto.current?.files;
    // make sure that it's not null or undefined
    if (files) {
      const formData = new FormData();
      formData.append("avatar", files[0]);
    }
    // need to set something
  };

  return (
    <input
      id="avatar"
      accept="image/*"
      type="file"
      ref={inputUpdateAvatarPhoto}
      onInput={(e) => {
        handleImageChange(e);
      }}
    />
  );
};

You Don't Need a Ref

See how your handleImageChange function gets an event e, but doesn't use it? inputUpdateAvatarPhoto.current is the same as e.currentTarget!

We actually don't even need a handler on the input though, because you can get a FormData object for the whole form! Check out this example in the MDN docs: Sending files using a FormData object.

We want to set the name property on the input since that's what's used to determine its key in the FormData object.

const ProfileLayoutV2: React.FC = ({ children }) => {

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    // prevent the page from redirecting ot reloading
    e.preventDefault();
    // get the `FormData` for the whole form
    const formData = new FormData(e.currentTarget);
    // logs a `File` object
    console.log(formData.get("avatar"));
  };

  return (
    <form name="profile_form" onSubmit={handleSubmit}>
      <input
        id="avatar"
        name="avatar"
        accept="image/*"
        type="file"
      />
      <button type="submit">Submit</button>
    </form>
  );
};

Note that if you want to use the File directly, you'll need to check that it's defined.

const avatar = formData.get("avatar"); // type is `string | File | null`
if ( avatar instanceof File ) {
  console.log("we have a file", avatar); // type is now just `File`
}
like image 196
Linda Paiste Avatar answered Jun 14 '26 12:06

Linda Paiste



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!