New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SolidJS]: How to handle errors from server? #189
Labels
question
Further information is requested
Comments
Okay I think I've figured it out but it seems a bit quirky, please let me know if there is a better way? Action code: const login = action(async (values: LoginForm) => {
"use server";
const result = safeParse(LoginSchema, values);
if (!result.success) {
const flattened = flatten<typeof LoginSchema>(result.issues);
const errors = Object.entries(flattened.nested).reduce(
(acc, [key, value]) => {
acc[key] = value[0];
return acc;
},
{} as { [key: string]: string },
);
if (flattened.root && flattened.root.length > 0) {
return new FormError<LoginForm>(flattened.root[0], errors);
}
return new FormError<LoginForm>(errors);
}
return new FormError<LoginForm>("Email exists in database");
}); Submit code: const [loginForm, { Form, Field }] = createForm<LoginForm>({});
const act = useAction(login);
const sub = useSubmission(login);
const handleSubmit: SubmitHandler<LoginForm> = async (values) => {
await act(values);
if (sub.result) {
Object.entries(sub.result.errors).forEach(([field, message]) => {
setError(loginForm, field as keyof LoginForm, message);
});
throw new FormError<LoginForm>(sub.result.message);
}
}; |
Hey, I haven't had time to take a closer look at the new SolidStart beta release. I plan to integrate it in the future with a nice API and DX, but that will take some time. |
Hello, I end up with something like that to reuse on different form/action. //@types/action.d.ts
import { FieldValues, FormErrors } from "@modular-forms/solid";
import { Action } from "@solidjs/router";
export type ActionForm<Schema extends FieldValues> = Action<
[data: Schema],
{ success?: boolean; error?: string; fields?: FormErrors<Schema> } | void
>;
// autocomplete on fields from TS //lib/utils.ts
export function flatIssues<K extends string | number>(
issues: SchemaIssues,
): { [key in K]?: string } {
let errors: { [key in K]?: string } = issues ? {} : {};
return issues.reduce((acc, issue) => {
if (
issue.path?.every(
({ key }) => typeof key === "string" || typeof key === "number",
)
) {
const key = issue.path!.map(({ key }) => key).join(".") as K;
if (acc[key]) {
acc[key] = acc[key] + "\n" + issue.message; // merge multiple issues, split in components
} else acc[key] = issue.message;
}
return acc;
}, errors);
} //login.tsx
export default function Index() {
const action = useAction(login);
const submission = useSubmission(login);
const [loginForm, { Form, Field }] = createForm<LoginForm>({
validate: valiForm(LoginSchema),
});
const handleSubmit: SubmitHandler<LoginForm> = async (values) => {
await action(values);
if (submission.result) {
const { error = "", fields = {} } = submission.result;
throw new FormError<LoginForm>(error, fields);
}
};
return ( ... );
};
const LoginSchema = v.object({ ... })
type LoginForm = v.Input<typeof LoginSchema>;
const login: ActionForm<LoginForm> = action(async (data) => {
"use server";
const result = v.safeParse(LoginSchema, data);
if (!result.success) {
const errors = flatIssues<keyof LoginForm>(result.issues);
return { fields: errors };
}
const { username, password } = result.output;
// db call
if (failed) return { error: "user does not exist" };
// all good
throw redirect("/");
}, "login"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I'm wondering how I can handle server errors when I submit my form? Ie think a login form but the email has already been taken etc..
Schema/Type code:
Component code:
Action code:
I would have thought I would see a message here, but I only see 500 internal server errors in my network tab:
The text was updated successfully, but these errors were encountered: