import React, { useCallback, useContext, useEffect, useMemo, useReducer } from 'react'; import SimpleReactValidator from 'simple-react-validator'; const ValidatorContext = React.createContext(null as any); const ValidatorOptions = React.createContext(null as any); export function ValidatorOptionProvider({ value, children }) { const previousOptions = useContext(ValidatorOptions); const combinedOptions = useMemo(() => ({ ...(previousOptions || {}), ...(value || {}), messages: { ...((previousOptions || {}).messages || {}), ...((value || {}).messages || {}) }, validators: { ...((previousOptions || {}).validators || {}), ...((value || {}).validators || {}) } }), [value, previousOptions]); return { children } ; } export function useValidator() { return useContext(ValidatorContext)[0]; } export function useValidate(name: string|null, value:any = null, type:any = null) { const validator = useValidator(); useEffect(function() { if (validator && name) { return function() { delete validator.fields[name]; delete validator.errorMessages[name]; }; } }, [ validator, name ]); return validator.message(name, value, type || []); } export function ValidatorProvider({ children }) { const options = useContext(ValidatorOptions); const [,forceUpdate] = useReducer(x => ++x, 0); const validator = useMemo(() => new SimpleReactValidator({ ...options, autoForceUpdate: { forceUpdate }}), [options, forceUpdate]); const state = useMemo(() => ([validator, validator.messagesShown]), [validator, validator.messagesShown]); const handleSubmit = useCallback(function(e: Event) { if (!validator.allValid()) { e.preventDefault(); e.stopPropagation(); if (!validator.messagesShown) { validator.showMessages(); forceUpdate(); } return ; } if (validator.messagesShown) { validator.hideMessages(); forceUpdate(); } children.props.onSubmit && children.props.onSubmit(e); }, [validator, children.props.onSubmit, forceUpdate]); return { React.cloneElement(children, { onSubmit: handleSubmit }) } ; }