I am using Svelte and the Skeleton UI toolkit to write a function that will be triggered when the user clicks a Delete button and will perform the following steps:
- Show the user a confirmation dialog, to check that they really want to perform the deletion
- Make an Axios
delete()
call to perform the deletion on the server - If the deletion succeeds, refresh the page with
invalidateAll()
- If the deletion fails, show an alert dialog with the response message
Unfortunately, at point 4 I am seeing the alert dialog flash up only momentarily and then disappear (and then DOM errors are generated when clicking the page). Because of this, I had assumed that this was a bug with the Skeleton Modal component. I was going to raise an issue there, and was producing a minimal page for reproducing it - but in doing that, I discovered that if I removed the axios call and replaced it with just a simple thrown Error then the problem doesn't happen. So I guess it is some problem with the way I am using axios or handling its errors.
This is my Svelte page:
<script lang="ts">
import { modalStore } from '@skeletonlabs/skeleton';
import { invalidateAll } from '$app/navigation';
import type { ModalSettings } from '@skeletonlabs/skeleton';
import axios from 'axios';
async function deleteEntity(entityType: string, body: string, url: string) {
const errorMessage = await new Promise<string | void>((resolve) => {
const deleteModal: ModalSettings = {
type: 'confirm',
title: `Delete ${entityType}?`,
body: body,
response: async (r: boolean) => {
if (r) {
try {
await axios.delete(url);
// throw new Error("failed"); // this works
} catch (error: any) {
resolve("oops");
}
}
resolve(undefined);
}
};
modalStore.trigger(deleteModal);
});
modalStore.close();
console.log(`errorMessage: ${errorMessage}`);
if (errorMessage) {
const errorModal: ModalSettings = {
type: 'alert',
title: `Could not delete ${entityType}`,
body: errorMessage,
buttonTextCancel: 'OK'
};
console.log("show error");
modalStore.trigger(errorModal);
// setTimeout(() => modalStore.trigger(errorModal), 1000); // this works, but is unsatisfactory
} else {
invalidateAll();
}
console.log("done");
}
</script>
<div>
<button on:click="{() => deleteEntity("Entity", 'Really delete it?', '/api/plans/24')}">Delete</button>
</div>
If I comment out the call to axios and replace it with the direct throwing of a new error, it works as expected. With axios, the only way I can get it to work is to show the error dialog with some delay (the commented out code at the bottom of the function). This tells me that there is some race condition - presumably because I am not correctly handling the asynchronous nature of the axios requests. I have replaced the try/catch
block with an equivalent flow using .then()
and .catch()
but I still see the same results.
What have I done wrong?