Home > Software engineering >  ref to form element is null when submitting the form
ref to form element is null when submitting the form

Time:12-23

I have a form that is supposed to upload a file (image) to a NextJs API route. I try to retrieve the form values using a ref to the form. However when I try to access the form in the onSubmit function, the ref is still null. I am aware that refs can be null on first render, but I assume that by the time a form is submitted, the ref should be resolved.

This is what the form looks likes:

<form ref={formRef} onSubmit={onFormSubmit}>
  <label htmlFor="image">Image:</label>
  <input id="image" accept="image/*" multiple={false} onChange={onImageChange} name="image" type="file" required />
  <button type="submit">Upload</button>
</form>

This is what the rest of the (function) component looks like:

const UploadImageModal = (): JSX.Element => {
  const formRef = useRef<HTMLFormElement>(null)
  const onFormSubmit = async (event: SubmitEvent) => {
    event.preventDefault()
    console.log(formRef.current) //Shows null
    const data = new FormData(formRef.current)
    const res = await fetch('/api/upload-image', {
      method: 'POST',
      body: data
    })
  }
  
  return (/* The component including the form */)
}

I am using TypeScript, however I don't think that is relevant, since TypeScript has no influence during runtime. I left out anything that I believe to be irrelevant to this question like styling and the rest of the component that doesn't touch the form.

The API route has been tested using Postman and is working as supposed. If there is a way to get the formdata directly from the SubmitEvent that would also be a good solution. I thought the formdata would be exposed through that event, but it didn't get me anywhere.

Thanks to anyone taking the time to help me out!

CodePudding user response:

You can get form DOM reference by

const data = new FormData(event.target)

[info] You are using typescript so the type of the handler should be

const onFormSubmit: FormEventHandler<HTMLFormElement > = async (event) => {

CodePudding user response:

I attached the working code and also Codesandbox below. https://codesandbox.io/s/react-functional-component-form-usage-with-typescript-16ghf?file=/src/App.tsx

import "./styles.css";
import { SyntheticEvent, useRef } from "react";

const UploadImageModal = (): JSX.Element => {
  const formRef = useRef() as React.MutableRefObject<HTMLFormElement>;

  const onFormSubmit = async (event: SyntheticEvent) => {
    event.preventDefault();
    console.log(formRef); //Shows null
    const data = new FormData(formRef.current);
    const res = await fetch("/api/upload-image", {
      method: "POST",
      body: data
    });
  };

  return (
    <form ref={formRef} onSubmit={onFormSubmit}>
      <label htmlFor="image">Image:</label>
      <input
        id="image"
        accept="image/*"
        multiple={false}
        name="image"
        type="file"
        required
      />
      <button type="submit">Upload</button>
    </form>
  );
};

export default function App() {
  return (
    <div className="App">
      <UploadImageModal />
    </div>
  );
}
  • Related