Skip to content

Commit 7b1597b

Browse files
committedMar 7, 2024
Add errors to actions
1 parent 6df4a7a commit 7b1597b

File tree

4 files changed

+31
-16
lines changed

4 files changed

+31
-16
lines changed
 

‎.changeset/hot-kiwis-applaud.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solidjs/router": minor
3+
---
4+
5+
Add errors to actions

‎src/data/action.ts

+23-14
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,32 @@ export function useSubmission<T extends Array<any>, U>(
5151
}
5252

5353
export function useAction<T extends Array<any>, U>(action: Action<T, U>) {
54-
const router = useRouter();
55-
return (...args: Parameters<Action<T, U>>) => action.apply(router, args);
54+
const r = useRouter();
55+
return (...args: Parameters<Action<T, U>>) => action.apply({r}, args);
5656
}
5757

5858
export function action<T extends Array<any>, U = void>(
5959
fn: (...args: T) => Promise<U>,
6060
name?: string
6161
): Action<T, U> {
62-
function mutate(this: RouterContext, ...variables: T) {
63-
const router = this;
62+
function mutate(this: { r: RouterContext, f?: HTMLFormElement }, ...variables: T) {
63+
const router = this.r;
64+
const form = this.f;
6465
const p = (
6566
router.singleFlight && (fn as any).withOptions
6667
? (fn as any).withOptions({ headers: { "X-Single-Flight": "true" } })
6768
: fn
6869
)(...variables);
69-
const [result, setResult] = createSignal<{ data?: U }>();
70+
const [result, setResult] = createSignal<{ data?: U, error?: any }>();
7071
let submission: Submission<T, U>;
71-
async function handler(res: any) {
72-
const data = await handleResponse(res as any, router.navigatorFactory());
73-
data ? setResult({ data }) : submission.clear();
74-
return data;
72+
function handler(error?: boolean) {
73+
return async (res: any) => {
74+
const result = await handleResponse(res, error, router.navigatorFactory());
75+
if (!result) return submission.clear();
76+
setResult(result);
77+
if (result.error && !form) throw result.error;
78+
return result.data;
79+
};
7580
}
7681
router.submissions[1](s => [
7782
...s,
@@ -81,6 +86,9 @@ export function action<T extends Array<any>, U = void>(
8186
get result() {
8287
return result()?.data;
8388
},
89+
get error() {
90+
return result()?.error;
91+
},
8492
get pending() {
8593
return !result();
8694
},
@@ -90,11 +98,11 @@ export function action<T extends Array<any>, U = void>(
9098
retry() {
9199
setResult(undefined);
92100
const p = fn(...variables);
93-
return p.then(handler, handler);
101+
return p.then(handler(), handler(true));
94102
}
95103
})
96104
]);
97-
return p.then(handler, handler);
105+
return p.then(handler(), handler(true));
98106
}
99107

100108
const url: string =
@@ -134,7 +142,7 @@ function toAction<T extends Array<any>, U>(fn: Function, url: string): Action<T,
134142
const hashString = (s: string) =>
135143
s.split("").reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0);
136144

137-
async function handleResponse(response: Response, navigate: Navigator) {
145+
async function handleResponse(response: unknown, error: boolean | undefined, navigate: Navigator) {
138146
let data: any;
139147
let keys: string[] | undefined;
140148
let invalidateKeys: string[] | undefined;
@@ -162,10 +170,11 @@ async function handleResponse(response: Response, navigate: Navigator) {
162170
navigate(locationUrl);
163171
}
164172
}
165-
} else data = response;
173+
} else if (error) return { error: response };
174+
else data = response;
166175
// invalidate
167176
cacheKeyOp(invalidateKeys, entry => (entry[0] = 0));
168177
// trigger revalidation
169178
await revalidate(keys, false);
170-
return data;
179+
return data != null ? { data } : undefined;
171180
}

‎src/data/events.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export function setupNativeEvents(preload = true, explicitLinks = false, actionB
119119
(evt.submitter as HTMLButtonElement | HTMLInputElement).name,
120120
(evt.submitter as HTMLButtonElement | HTMLInputElement).value
121121
);
122-
handler.call(router, data);
122+
handler.call({ r: router, f: evt.target }, data);
123123
}
124124
}
125125

‎src/types.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ declare module "solid-js/web" {
1212
cache?: Map<string, CacheEntry>;
1313
submission?: {
1414
input: any;
15-
result?: any;
15+
result: any;
1616
url: string;
1717
};
1818
dataOnly?: boolean | string[];
@@ -194,6 +194,7 @@ export interface BeforeLeaveLifecycle {
194194
export type Submission<T, U> = {
195195
readonly input: T;
196196
readonly result?: U;
197+
readonly error: any;
Has a conversation. Original line has a conversation.
197198
readonly pending: boolean;
198199
readonly url: string;
199200
clear: () => void;

0 commit comments

Comments
 (0)
Please sign in to comment.