UNPKG

@matthew.ngo/reform

Version:

A flexible and powerful React form management library with advanced validation, state observation, and multi-group support

175 lines (157 loc) 5.1 kB
import { useMemo } from "react"; import { ObjectSchema, object as yupObject, AnyObject, Maybe, ValidationError } from "yup"; import { YupSchemaConfig } from "./types"; import { useYupContext } from "./useYupContext"; import { useYupTransformers } from "./useYupTransformers"; import { ReformReturn } from "../../../types"; import { ReformYupIntegration } from "../types"; /** * Hook for enhanced Yup integration with Reform * * @template T - The type of form data * @param reform - The Reform hook return value * @returns Object with enhanced Yup integration utilities * * @example * // Basic usage * const reform = useReform(config); * const yupIntegration = useReformYupIntegration(reform); * * // Create an enhanced schema with transformers and context * const enhancedSchema = yupIntegration.createEnhancedSchema(baseSchema); * * // Register a transformer for date fields * useEffect(() => { * const unregister = yupIntegration.registerTransformer({ * field: 'birthDate', * transformer: (value) => value instanceof Date ? value : new Date(value), * transformOn: 'input' * }); * * return unregister; * }, []); * * // Validate with context * const validateGroup = async (groupIndex) => { * const result = await yupIntegration.validateWithContext( * reform.getGroupData(groupIndex), * groupIndex * ); * * if (result.error) { * console.log(result.error); * } * }; */ export const useReformYupIntegration = <T extends Record<string, any> & AnyObject>( reform: ReformReturn<T> ): ReformYupIntegration<T> => { // Get form groups from reform const groups = reform.getGroups(); // Initialize Yup context and transformers hooks const yupContext = useYupContext<T>(groups); const yupTransformers = useYupTransformers<T>(groups); /** * Create an enhanced schema with both transformers and context */ const createEnhancedSchema = useMemo( () => (baseSchema: ObjectSchema<T>, config?: Partial<YupSchemaConfig<T>>) => { // First apply transformers const schemaWithTransformers = yupTransformers.createSchemaWithTransformers(baseSchema); // Then add context support const enhancedSchema = yupContext.createSchemaWithContext( schemaWithTransformers ); return enhancedSchema; }, [yupContext, yupTransformers] ); /** * Validate data with context for a specific group */ const validateWithContext = useMemo( () => async (data: T, groupIndex: number, fieldPath?: string): Promise<{ value: T | null; error: any }> => { // Create validation context const context = yupContext.createValidationContext( groupIndex, fieldPath as any ); // Ưu tiên sử dụng groupSchema nếu có let groupSchema = reform.config.groupSchema; // Nếu không có groupSchema, thử sử dụng groupsSchema if (!groupSchema && reform.config.groupsSchema) { // groupsSchema là schema cho mảng các group, không phải cho một group // Không thể sử dụng trực tiếp console.warn( "groupsSchema is for array of groups, not for a single group" ); } // Nếu không có schema nào phù hợp, trả về data mà không validate if (!groupSchema) { return { value: data, error: null }; } try { // Create enhanced schema const enhancedSchema = createEnhancedSchema(groupSchema); // Validate with context const result = await (enhancedSchema as any).validateWithContext( data, context ); return result; } catch (error) { // Format validation error with enhanced context const formattedError = yupContext.formatValidationError( error as ValidationError, groupIndex ); return { value: null, error: formattedError }; } }, [ reform.config.groupSchema, reform.config.groupsSchema, yupContext, createEnhancedSchema, ] ); /** * Update context data for both context and transformers */ const updateContextData = useMemo( () => (data: Record<string, any>) => { yupContext.updateContextData(data); yupTransformers.updateContextData(data); }, [yupContext, yupTransformers] ); return useMemo( () => ({ // Expose methods from both hooks ...yupContext, ...yupTransformers, // Enhanced methods createEnhancedSchema, validateWithContext, updateContextData, // Helper method to validate all groups validateAllGroups: async () => { const results: Array<{ value: T | null; error: any }> = []; for (let i = 0; i < groups.length; i++) { results.push(await validateWithContext(groups[i].data, i)); } return results; }, }), [ yupContext, yupTransformers, createEnhancedSchema, validateWithContext, updateContextData, groups, ] ); };