My react app is for ticket sale that takes an existing image and stamps the guest name on it (using canvas). I have this form that sends a formData to the server
<Formik
validationSchema={schema}
onSubmit={async (values) => {
try {
// Create a canvas element, add the image and text, covert to blob
//for 1500 x 485 images
var canvas = document.createElement("canvas");
var layout = canvas.getContext("2d");
let ticket = new Image();
ticket.src = target.ticket_img;
//image
canvas.width = ticket.naturalWidth;
canvas.height = ticket.naturalHeight;
layout.drawImage(
ticket,
0,
0,
ticket.naturalWidth,
ticket.naturalHeight
);
// text
let textName = values.name;
layout.rotate(4.71);
layout.font = "52px Archive";
layout.fillStyle = "#faf9f6";
layout.textAlign = "center";
layout.strokeText(textName, -255, 1170);
layout.fillText(textName, -255, 1170);
layout.font = "52px Archive";
layout.fillStyle = "#faf9f6";
let textSurname = values.surname;
layout.textAlign = "center";
layout.strokeText(textSurname, -255, 1230);
layout.fillText(textSurname, -255, 1230);
// blob
const dataBlob = await new Promise((resolve) =>
canvas.toBlob((blob) => resolve(blob), "image/webp")
);
// formData
const formData = new FormData();
formData.append(
"image",
dataBlob,
target.title +
"_" +
values.name +
values.surname +
"_GUEST"
);
// some more code that is not causing any errors
} catch (err) {
console.log(err)
}
the problem is that when I first submit, I get the following error that comes from the catch block with console.log
TypeError: Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'. at onSubmit (NonMemberPurchase.jsx:135:1)
and on the second submit (pressing the button once again), the form is submitted without problems and without errors. I suspect that I am scheduling the events poorly but I do not know how to fix it. I also do not want to change the canvas to blob converting functionality as this once works and the others do not output the ticket canvas properly. I am currently using the code as it is but people have started noticing the bug and start complaining that they need to press twice for the form to be submitted. I would appreciate some suggestions!
Okay so after some sessions I was finally able to figure it out! I shifted my convert canvas to Blob function out of the scope
export const createCustomerTicket = async (ticketImage, name, surname) => {
// Create a canvas element, add the image and text, covert to blob
//for 1500 x 485 images
var canvas = document.createElement("canvas");
var layout = canvas.getContext("2d");
let ticket = new Image();
ticket.src = ticketImage;
await new Promise((resolve, reject) => {
ticket.onload = resolve;
ticket.onerror = reject;
});
//image
canvas.width = ticket.naturalWidth;
canvas.height = ticket.naturalHeight;
layout.drawImage(
ticket,
0,
0,
ticket.naturalWidth,
ticket.naturalHeight
);
// text
layout.rotate(4.71);
layout.font = "52px Archive";
layout.fillStyle = "#faf9f6";
layout.textAlign = "center";
layout.strokeText(name, -255, 1170);
layout.fillText(name, -255, 1170);
layout.font = "52px Archive";
layout.fillStyle = "#faf9f6";
layout.textAlign = "center";
layout.strokeText(surname, -255, 1230);
layout.fillText(surname, -255, 1230);
// blob
const dataBlob = await new Promise((resolve) =>
canvas.toBlob((blob) => resolve(blob), "image/webp")
);
return dataBlob
}
Then I just call it async in the submit handler
<Formik
validationSchema={schema}
onSubmit={async (values) => {
try {
const ticket = await createCustomerTicket(target.ticket_img, values.name, values.surname);
// formData
const formData = new FormData();
formData.append(
"image",
ticket,
target.title +
"_" +
values.name +
values.surname +
"_GUEST"
);
//other code
It works like a charm and I do not get it as a null value anymore!