From d0c3af41f94510cd154752e4cc303ca7664cff8f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 15:40:20 +0000
Subject: [PATCH 1/4] Initial plan
From 6efc6e7973ea909b7eb79fa4e85ce52550d98e18 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 15:43:12 +0000
Subject: [PATCH 2/4] fix: surface errors from useAsyncCallback in
examples/base
Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/848c6a14-640a-4fb5-8f04-f3f09fbbedf8
Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
---
examples/base/src/Content.tsx | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/examples/base/src/Content.tsx b/examples/base/src/Content.tsx
index 8046a07..4759a07 100644
--- a/examples/base/src/Content.tsx
+++ b/examples/base/src/Content.tsx
@@ -6,14 +6,14 @@ import { useAuthClient } from './auth';
export const Content: React.FC = () => {
const authClient = useAuthClient();
- const [doLogin, isLoginLoading] = useAsyncCallback(() => authClient.login(), [
+ const [doLogin, isLoginLoading, loginError] = useAsyncCallback(() => authClient.login(), [
authClient,
]);
- const [doRefresh, isRefreshLoading] = useAsyncCallback(
+ const [doRefresh, isRefreshLoading, refreshError] = useAsyncCallback(
() => authClient.refresh(),
[authClient]
);
- const [doLogout, isLogoutLoading] = useAsyncCallback(
+ const [doLogout, isLogoutLoading, logoutError] = useAsyncCallback(
() => authClient.logout(),
[authClient]
);
@@ -49,6 +49,10 @@ export const Content: React.FC = () => {
{isLoginLoading ?
Login in progress..
: null}
{isRefreshLoading ? Refresh in progress..
: null}
+ {loginError != null ? Login error: {loginError instanceof Error ? loginError.message : 'An error occurred'}
: null}
+ {refreshError != null ? Refresh error: {refreshError instanceof Error ? refreshError.message : 'An error occurred'}
: null}
+ {logoutError != null ? Logout error: {logoutError instanceof Error ? logoutError.message : 'An error occurred'}
: null}
+
Tokens:
{JSON.stringify(authClient.tokens, null, 2)}
@@ -58,16 +62,20 @@ export const Content: React.FC = () => {
function useAsyncCallback Promise>(
callback: T,
deps: DependencyList
-): [T, boolean] {
+): [T, boolean, unknown] {
const [isLoading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
const cb = useCallback(async (...argsx: never[]) => {
setLoading(true);
+ setError(null);
try {
return await callback(...argsx);
+ } catch (err) {
+ setError(err);
} finally {
setLoading(false);
}
}, deps) as T;
- return [cb, isLoading];
+ return [cb, isLoading, error];
}
From ab28bff1f77963635b701decad0d64ef6fbbb311 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 17:12:54 +0000
Subject: [PATCH 3/4] fix(examples): combine isLoading and error into single
state in useAsyncCallback
Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/7c5e293b-c00b-42f6-bdca-56b3c09b79bf
Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
---
examples/base/src/Content.tsx | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/examples/base/src/Content.tsx b/examples/base/src/Content.tsx
index 4759a07..eaadeef 100644
--- a/examples/base/src/Content.tsx
+++ b/examples/base/src/Content.tsx
@@ -59,22 +59,25 @@ export const Content: React.FC = () => {
);
};
+type AsyncCallbackState = { isLoading: boolean; error: unknown };
+
function useAsyncCallback Promise>(
callback: T,
deps: DependencyList
): [T, boolean, unknown] {
- const [isLoading, setLoading] = useState(false);
- const [error, setError] = useState(null);
+ const [{ isLoading, error }, setState] = useState({
+ isLoading: false,
+ error: null,
+ });
const cb = useCallback(async (...argsx: never[]) => {
- setLoading(true);
- setError(null);
+ setState({ isLoading: true, error: null });
try {
return await callback(...argsx);
} catch (err) {
- setError(err);
- } finally {
- setLoading(false);
+ setState({ isLoading: false, error: err });
+ return;
}
+ setState({ isLoading: false, error: null });
}, deps) as T;
return [cb, isLoading, error];
From f2d184d0ced5877b175c72e0f6d436b83db21a1c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 17:15:50 +0000
Subject: [PATCH 4/4] fix(examples): address review feedback - role=alert,
Parameters typing, fix unreachable setState
Agent-Logs-Url: https://github.com/forwardsoftware/react-auth/sessions/7e291b86-a295-4acd-967f-d5249adc4d40
Co-authored-by: panz3r <1754457+panz3r@users.noreply.github.com>
---
examples/base/src/Content.tsx | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/examples/base/src/Content.tsx b/examples/base/src/Content.tsx
index eaadeef..2244ee8 100644
--- a/examples/base/src/Content.tsx
+++ b/examples/base/src/Content.tsx
@@ -49,9 +49,9 @@ export const Content: React.FC = () => {
{isLoginLoading ? Login in progress..
: null}
{isRefreshLoading ? Refresh in progress..
: null}
- {loginError != null ? Login error: {loginError instanceof Error ? loginError.message : 'An error occurred'}
: null}
- {refreshError != null ? Refresh error: {refreshError instanceof Error ? refreshError.message : 'An error occurred'}
: null}
- {logoutError != null ? Logout error: {logoutError instanceof Error ? logoutError.message : 'An error occurred'}
: null}
+ {loginError != null ? Login error: {loginError instanceof Error ? loginError.message : 'An error occurred'}
: null}
+ {refreshError != null ? Refresh error: {refreshError instanceof Error ? refreshError.message : 'An error occurred'}
: null}
+ {logoutError != null ? Logout error: {logoutError instanceof Error ? logoutError.message : 'An error occurred'}
: null}
Tokens:
{JSON.stringify(authClient.tokens, null, 2)}
@@ -64,21 +64,21 @@ type AsyncCallbackState = { isLoading: boolean; error: unknown };
function useAsyncCallback Promise>(
callback: T,
deps: DependencyList
-): [T, boolean, unknown] {
+): [(...args: Parameters) => Promise, boolean, unknown] {
const [{ isLoading, error }, setState] = useState({
isLoading: false,
error: null,
});
- const cb = useCallback(async (...argsx: never[]) => {
+ const cb = useCallback(async (...argsx: Parameters) => {
setState({ isLoading: true, error: null });
try {
- return await callback(...argsx);
+ const result = await callback(...argsx);
+ setState({ isLoading: false, error: null });
+ return result;
} catch (err) {
setState({ isLoading: false, error: err });
- return;
}
- setState({ isLoading: false, error: null });
- }, deps) as T;
+ }, deps);
return [cb, isLoading, error];
}