refactor useValidation hook

This commit is contained in:
Chika 2020-09-09 22:26:16 +03:00
parent a1102d5f9c
commit 0c4cb602fd
5 changed files with 84 additions and 45 deletions

View File

@ -12,6 +12,7 @@ const Input = ({
readonly,
type,
validation,
rules,
pattern,
prefix,
suffix,
@ -19,38 +20,30 @@ const Input = ({
addonBefore,
addonAfter,
valueName,
computedValue
computedValue,
}) => {
const { value, setCurrentValue, debouncedValue } = useStoreValue({
computedValue,
valueName,
debounceDelay: TEXT_INPUT_DEBOUNCE_DELAY
debounceDelay: TEXT_INPUT_DEBOUNCE_DELAY,
});
const { status } = useStatus(name);
const { errorMessage, validator } = validation || {
errorMessage: '',
validator: () => {}
};
const { isValid } = useValidation({ value: debouncedValue, validator });
const getValidateStatus = () => {
if (!debouncedValue) {
return undefined;
}
return isValid === false ? 'error' : 'success';
};
const getHelpMessage = () => {
if (!debouncedValue) {
return undefined;
}
return isValid === false && errorMessage;
};
const { isValid, validateStatus, message } = useValidation({
elementName: name,
value: debouncedValue,
validation: validation || {
errorMessage: '',
validator: () => {},
},
});
return (
<Form.Item
hasFeedback
validateStatus={getValidateStatus()}
help={getHelpMessage()}
validateStatus={validateStatus}
help={message}
rules={rules}
>
<AntInput
prefix={prefix}

View File

@ -1,11 +0,0 @@
import { useEffect, useState } from 'react';
export const useValidation = ({ value, validator }) => {
const [isValid, setIsValid] = useState(false);
useEffect(() => {
const validationResult = validator(value);
setIsValid(validationResult);
}, [value, validator]);
return { isValid };
};

View File

@ -0,0 +1,47 @@
import { ValidateStatus } from 'antd/lib/form/FormItem';
import { ElementsNames } from 'core/types/elements';
import { useEffect, useState } from 'react';
import { useStores } from './useStores';
interface IUseValidationArgs {
elementName: ElementsNames;
value: any;
validation: { errorMessage: string; validator: Function };
}
export const useValidation = ({
elementName,
value,
validation: { validator, errorMessage },
}: IUseValidationArgs) => {
const [isValid, setIsValid] = useState(false);
const { calculationStore } = useStores();
useEffect(() => {
const validationResult = validator(value);
setIsValid(validationResult);
calculationStore.setValidation(elementName, validationResult);
}, [value, validator, calculationStore, elementName]);
const getValidateStatus = (): ValidateStatus | undefined => {
if (!value) {
return undefined;
}
return isValid === false ? 'error' : 'success';
};
const getMessage = (): string | undefined => {
if (!value) {
return undefined;
}
if (isValid === false) {
return errorMessage;
}
};
return {
isValid,
validateStatus: getValidateStatus(),
message: getMessage(),
};
};

View File

@ -16,25 +16,32 @@ import { ICalculationStore } from 'core/types/stores';
const CalculationStore: ICalculationStore = observable(
assignProperties(
{
statuses: initialStatuses,
validations: {},
values: initialValues,
options: initialOptions,
filters: {},
getValue(sourceValueName: ValuesNames) {
return this.values[sourceValueName];
},
setValue(sourceValueName: ValuesNames, newValue: any) {
this.values[sourceValueName] = newValue;
},
statuses: initialStatuses,
getStatus(elementName: ElementsNames) {
return this.statuses[elementName];
},
setValue(sourceValueName: ValuesNames, newValue: any) {
this.values[sourceValueName] = newValue;
},
setStatus(elementName: ElementsNames, status: Status) {
this.statuses[elementName] = status;
},
validations: {},
getValidation(elementName: ElementsNames) {
return this.validations[elementName];
},
setValidation(elementName: ElementsNames, validation: boolean) {
this.validations[elementName] = validation;
},
options: initialOptions,
filters: {},
},
computedEffects,
),

View File

@ -3,15 +3,18 @@ import { TElements, ElementsNames } from './elements';
import { TStatuses, Status } from './statuses';
export interface ICalculationStore {
statuses: TStatuses;
validations: TElements<boolean>;
values: TValues;
options: TElements<any>;
filters: TElements<any>;
values: TValues;
getValue: (sourceValueName: ValuesNames) => any;
getStatus: (elementName: ElementsNames) => Status;
setValue: (sourceValueName: ValuesNames, newValue: any) => void;
statuses: TStatuses;
getStatus: (elementName: ElementsNames) => Status;
setStatus: (elementName: ElementsNames, status: Status) => void;
validations: TElements<boolean>;
getValidation: (elementName: ElementsNames) => boolean;
setValidation: (elementName: ElementsNames, validation: boolean) => void;
}