Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I modify formData before sending it?

How to modify the code so that after submitting the image changes to base64 code and so that I can use the formData from the form in the subpage component.

At the moment the AddForm look like this:

import { Form, useNavigation } from 'react-router-dom';
import classes from './AuthForm.module.css';

function AddForm() {
  const navigation = useNavigation() 
  const isSubmitting =navigation.state === 'submitting'

  function fileToBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
  
      reader.onload = () => {
        const base64 = reader.result;
        resolve(base64);
      };
  
      reader.onerror = (error) => {
        reject(error);
      };
    });
  }

  function handleFileInputChange(event) {
    const file = event.target.files[0];
  
    fileToBase64(file)
      .then((base64) => {
        console.log(base64);
      })
      .catch((error) => {
        console.error(error);
      });
  }
  
  return (
    <>
      <Form method="post" className={classes.form}>
      <div>
        <label htmlFor="title">Tytuł:</label>
        <input
          type="text"
          id="title"
          name='title'
        />
      </div>
      <div>
        <label htmlFor="file">Wybierz plik:</label>
        <input
          type="file"
          id="file"
          name='title'
          onChange={handleFileInputChange}
        />
      </div>
      <button disabled={isSubmitting}>{isSubmitting ? 'Adding...' : 'Add'}</button>
      </Form>
      </>
  );
}

export default AddForm;

And component where I use it look like this:

import AddForm from '../components/AddForm';

function AddPage() {
  return <AddForm/>; 
}

export default AddPage;

export async function action({ request }) { 
  const data = await request.formData();
  console.log(data)
  const postData = { 
    titlt: data.get('title'),
    file: data.get('file'),
  };
  console.log(postData)
}

I already tried to modify data in the next component but the file field in formData was null.

like image 481
Rolegur Avatar asked Feb 23 '26 23:02

Rolegur


1 Answers

It seems the problem is that you have an onChange handler in the component that takes the input's value and converts it to a base64 value but then doesn't do anything with it, meanwhile, the route's action function only reads/accesses the form fields' current values, which will only be the file name.

Add some state to store the base64 converted file string and add a hidden field to the form to hold this value. The action function can access this field value.

You also had a typo in the file input where the input had the same name attribute as the title input.

Example:

function AddForm() {
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";

  const [base64File, setBase64File] = useState(""); // <-- local state

  function fileToBase64(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);

      reader.onload = () => {
        const base64 = reader.result;
        resolve(base64);
      };

      reader.onerror = (error) => {
        reject(error);
      };
    });
  }

  function handleFileInputChange(event) {
    const file = event.target.files[0];

    fileToBase64(file)
      .then((base64) => {
        console.log(base64);
        setBase64File(base64); // <-- update local state
      })
      .catch((error) => {
        console.error(error);
      });
  }

  return (
    <Form method="post" className={classes.form}>
      <div>
        <label htmlFor="title">Tytuł:</label>
        <input type="text" id="title" name="title" />
      </div>
      <div>
        <label htmlFor="file">Wybierz plik:</label>
        <input
          type="file"
          id="file"
          name="file" // <-- fix typo
          onChange={handleFileInputChange}
        />
      </div>
      <input
        name="base64File"
        value={base64File} // <-- set input's value
        hidden
        readyOnly
      />
      <button disabled={isSubmitting}>
        {isSubmitting ? "Adding..." : "Add"}
      </button>
    </Form>
  );
}
export async function action({ request }) {
  const data = await request.formData();
  console.log(data);

  const title = data.get("title");
  const file = data.get("base64File");

  const postData = {
    title,
    file
  };
  console.log(postData);

  ... business logic

  ... return response?
}

Demo

Edit how-can-i-modify-formdata-before-sending-it

like image 77
Drew Reese Avatar answered Feb 25 '26 13:02

Drew Reese