diff --git a/.changeset/real-boxes-admire.md b/.changeset/real-boxes-admire.md
new file mode 100644
index 00000000..73872780
--- /dev/null
+++ b/.changeset/real-boxes-admire.md
@@ -0,0 +1,5 @@
+---
+"@reactive-dot/react": minor
+---
+
+BREAKING: The query error resetter no longer accepts a specific error input; it now defaults to resetting all errors globally.
diff --git a/apps/docs/docs/getting-started/query.md b/apps/docs/docs/getting-started/query.md
index 74df4946..272fe79c 100644
--- a/apps/docs/docs/getting-started/query.md
+++ b/apps/docs/docs/getting-started/query.md
@@ -203,7 +203,7 @@ function QueryWithRefresh() {
## Retry failed query
-Error from queries can be caught and reset using `ErrorBoundary` & [`useQueryErrorResetter`](/api/react/function/useQueryErrorResetter) hook.
+Error from queries can be reset using `ErrorBoundary` & [`useQueryErrorResetter`](/api/react/function/useQueryErrorResetter) hook.
```tsx
import { useQueryErrorResetter } from "@reactive-dot/react";
@@ -226,12 +226,7 @@ function AppErrorBoundary() {
return (
{
- if (details.reason === "imperative-api") {
- const [error] = details.args;
- resetQueryError(error);
- }
- }}
+ onReset={() => resetQueryError()}
>
{/* ... */}
diff --git a/examples/react/src/app.tsx b/examples/react/src/app.tsx
index 2b88d7c1..59721474 100644
--- a/examples/react/src/app.tsx
+++ b/examples/react/src/app.tsx
@@ -68,12 +68,7 @@ function Example({ chainName }: ExampleProps) {
{
- if (details.reason === "imperative-api") {
- const [error] = details.args;
- resetQueryError(error);
- }
- }}
+ onReset={() => resetQueryError()}
>
Loading {chainName}...}>
{chainName}
@@ -85,13 +80,13 @@ function Example({ chainName }: ExampleProps) {
);
}
-function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
+function ErrorFallback({ resetErrorBoundary }: FallbackProps) {
return (
Oops, something went wrong!
-
diff --git a/packages/react/src/hooks/use-query-error-resetter.ts b/packages/react/src/hooks/use-query-error-resetter.ts
index 10375666..d3b481d5 100644
--- a/packages/react/src/hooks/use-query-error-resetter.ts
+++ b/packages/react/src/hooks/use-query-error-resetter.ts
@@ -1,11 +1,21 @@
-import { resetQueryError } from "../utils/jotai.js";
+import { atomFamilyErrorsAtom } from "../utils/jotai.js";
+import { useAtomCallback } from "jotai/utils";
+import { useCallback } from "react";
/**
* Hook for getting function to reset query error caught by error boundary
*
* @returns Function to reset caught query error
*/
-// eslint-disable-next-line @eslint-react/hooks-extra/no-redundant-custom-hook
export function useQueryErrorResetter() {
- return resetQueryError;
+ return useAtomCallback(
+ useCallback((get) => {
+ const atomFamilyErrors = get(atomFamilyErrorsAtom);
+
+ for (const error of atomFamilyErrors) {
+ error.atomFamily.remove(error.param);
+ atomFamilyErrors.delete(error);
+ }
+ }, []),
+ );
}
diff --git a/packages/react/src/utils/jotai.ts b/packages/react/src/utils/jotai.ts
index d7a8dc59..e8e3087d 100644
--- a/packages/react/src/utils/jotai.ts
+++ b/packages/react/src/utils/jotai.ts
@@ -1,34 +1,17 @@
-import { QueryError } from "@reactive-dot/core";
-import type { Atom, Getter } from "jotai";
+import { atom, type Atom, type Getter } from "jotai";
import { atomFamily } from "jotai/utils";
import type { AtomFamily } from "jotai/vanilla/utils/atomFamily";
import { Observable } from "rxjs";
import { catchError } from "rxjs/operators";
-export class AtomFamilyError extends QueryError {
- constructor(
- readonly atomFamily: AtomFamily,
- readonly param: unknown,
- message: string | undefined,
- options?: ErrorOptions,
- ) {
- super(message, options);
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- static fromAtomFamilyError>(
- error: TError,
- atomFamily: TAtomFamily,
- param: TAtomFamily extends AtomFamily
- ? Param
- : unknown,
- message?: string,
- ) {
- return new this(atomFamily, param, message, {
- cause: error,
- });
- }
-}
+export const atomFamilyErrorsAtom = atom(
+ () =>
+ new Set<{
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ atomFamily: AtomFamily;
+ param: unknown;
+ }>(),
+);
export function atomFamilyWithErrorCatcher<
TParam,
@@ -55,38 +38,35 @@ export function atomFamilyWithErrorCatcher<
const atomCatching: TAtomCreator = (read, ...args) => {
// @ts-expect-error complex sub-type
const readCatching: TRead = (...readArgs) => {
+ const addError = (error: T) => {
+ const get = readArgs[0] as Getter;
+ get(atomFamilyErrorsAtom).add({
+ atomFamily: baseAtomFamily,
+ param,
+ });
+ return error;
+ };
+
try {
const value = read(...readArgs);
if (value instanceof Promise) {
return value.catch((error) => {
- throw AtomFamilyError.fromAtomFamilyError(
- error,
- baseAtomFamily,
- param,
- );
+ throw addError(error);
});
}
if (value instanceof Observable) {
return value.pipe(
catchError((error) => {
- throw AtomFamilyError.fromAtomFamilyError(
- error,
- baseAtomFamily,
- param,
- );
+ throw addError(error);
}),
);
}
return value;
} catch (error) {
- throw AtomFamilyError.fromAtomFamilyError(
- error,
- baseAtomFamily,
- param,
- );
+ throw addError(error);
}
};
@@ -101,17 +81,3 @@ export function atomFamilyWithErrorCatcher<
return baseAtomFamily;
}
-
-export function resetQueryError(error: unknown) {
- if (!(error instanceof Error)) {
- return;
- }
-
- if (error instanceof AtomFamilyError) {
- error.atomFamily.remove(error.param);
- }
-
- if (error.cause instanceof Error) {
- resetQueryError(error.cause);
- }
-}