Home > Back-end >  How to prevent route change based on async function
How to prevent route change based on async function

Time:07-08

In my Next.js app, I'm calling an upload function which contains the then and catch functions.

export const uploadDocument = async (url: UploadURLs, file: File) => {
  const formData = new FormData();
  formData.append("file", file);
  await fetch(`${someEndpoint}`, {
    method: "POST",
    body: formData,
  })
    .then(() => notify(`Awesome, it worked.`, "success"))
    .catch(() => notify("An error occurred.", "error"));
};

Note: The notify function is a wrapper function firing a toast notification, and isn't really important to my question.

From my component, I'm calling the uploadDocument function. Everything is working, but I can't stop router.push(nextPage) from firing (shown below), regardless of whether the uploadDocument function succeeds or not.

I want to keep the then and catch logic inside the uploadDocument function, but also would like to have the calling component know whether or not the upload succeeded, so I could prevent the page change.

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    await uploadDocument(
      "certificate",
      file
    )
    router.push(nextPage); // This always fires, but should be conditional
  };

I tried to capture the result of the function call, but get undefined regardless of upload success/failure:

const result = await uploadDocument("certificate", file);
if (result.success) router.push(nextPage);

CodePudding user response:

Try this approach:

export const uploadDocument = (url: UploadURLs, file: File) => {
  const formData = new FormData();
  formData.append("file", file);
  return fetch(`${someEndpoint}`, {
    method: "POST",
    body: formData,
  })
};

Then you can catch the error with an try /catch

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
    
       await uploadDocument(
         "certificate",
         file
       )
       notify(`Awesome, it worked.`, "success")
       router.push(nextPage);
 
    } catch(err) {
       notify("An error occurred.", "error")
    }
  };

CodePudding user response:

I followed the advice of @kemicofa-ghost, as they pointed out in the comments, and arrived at a working solution.

export const uploadDocument = async (url: UploadURLs, file: File) => {
  const formData = new FormData();
  formData.append("file", file);

  try {
    await fetch(`${someEndpoint}`, {
      method: "POST",
      body: formData,
    });
    notify(`Your file ${file.name} was uploaded successfully`, "success");
    return true;
  } catch (error) {
    notify(
      "An error occurred while uploading the file. Please try again.",
      "error"
    );
    return false;
  }
};

And then:

const result = await uploadDocument(
  "certificate",
  companyInfo2.incorporationCertificate
);

if (result) router.push(nextPage);

CodePudding user response:

You can keep your logic in your function:

type UploadResponse = {
  error: boolean;
  message: string;
}
export const uploadDocument = async (url: UploadURLs, file: File): Promise<UploadResponse> => {
  try {

  const formData = new FormData();
  formData.append("file", file);
  await fetch(`${someEndpoint}`, {
    method: "POST",
    body: formData,
  })
  
    return {error: false, message: "Awesome, it worked"}
  } catch(e) {
    return {error: true, message: "An error occurred"}
  }
};

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    const result = await uploadDocument(
      "certificate",
      file
    )

    notify(result.message);
    if (!result.error) {
      router.push(nextPage);
    }
  };
  • Related