Files
probo/apps/console/src/hooks/useStateWithSchema.ts
2025-12-01 18:23:11 +04:00

41 lines
1022 B
TypeScript

import { z, ZodError, type ZodTypeAny } from "zod";
import { useCallback, useMemo, useState } from "react";
export function useStateWithSchema<T extends ZodTypeAny>(
schema: T,
initialValue: z.infer<T>,
) {
const [state, setState] = useState(initialValue);
const [value, errors] = useMemo((): [z.infer<T>, Record<string, string>] => {
try {
schema.parse(state);
return [schema.parse(state), {}];
} catch (error) {
if (error instanceof ZodError) {
return [
state,
Object.fromEntries(
error.issues.map((issue) => [
issue.path.join("."),
issue.message,
]) ?? [],
),
];
}
return [state, {}];
}
}, [state, schema]);
return {
rawValue: state,
value,
errors,
update: useCallback(
<TKey extends keyof z.infer<T>>(key: TKey, value: z.infer<T>[TKey]) => {
setState((prevState) => ({ ...prevState, [key]: value }));
},
[],
),
};
}