diff --git a/src/hooks/useAsset.ts b/src/hooks/useAsset.ts index 9e1cc160..737b87d3 100644 --- a/src/hooks/useAsset.ts +++ b/src/hooks/useAsset.ts @@ -10,6 +10,7 @@ import type { } from 'pixi.js'; import type { AssetRetryOptions } from '../typedefs/AssetRetryOptions.ts'; import type { AssetRetryState } from '../typedefs/AssetRetryState.ts'; +import type { ErrorCallback } from '../typedefs/ErrorCallback.ts'; const errorCache: Map = new Map(); @@ -19,10 +20,19 @@ export function useAsset( options: (UnresolvedAsset & AssetRetryOptions) | string, /** @description A function to be called when the asset loader reports loading progress. */ onProgress: ProgressCallback, + /** @description A function to be called when the asset loader reports loading progress. */ + onError?: ErrorCallback, ) { if (typeof window === 'undefined') { + /** + * This is a weird hack that allows us to throw the error during + * serverside rendering, but still causes it to be handled appropriately + * in Next.js applications. + * + * @see https://github.com/vercel/next.js/blob/38b3423160afc572ad933c24c86fc572c584e70b/packages/next/src/shared/lib/lazy-dynamic/bailout-to-csr.ts + */ throw Object.assign(Error('`useAsset` will only run on the client.'), { digest: 'BAILOUT_TO_CLIENT_SIDE_RENDERING', }); @@ -42,7 +52,14 @@ export function useAsset( // Rethrow the cached error if we are not retrying on failure or have reached the max retries if (state && (!retryOnFailure || state.retries > maxRetries)) { - throw state.error; + if (typeof onError === 'function') + { + onError?.(state.error); + } + else + { + throw state.error; + } } throw Assets diff --git a/src/typedefs/ErrorCallback.ts b/src/typedefs/ErrorCallback.ts new file mode 100644 index 00000000..a97e7e2d --- /dev/null +++ b/src/typedefs/ErrorCallback.ts @@ -0,0 +1 @@ +export type ErrorCallback = (error: Error) => void;