diff --git a/src/components/Form.js b/src/components/Form.js index f1ea795efa42..372c7a0c5d9b 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -6,7 +6,7 @@ import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; -import StringUtils from '@libs/StringUtils'; +import * as ValidationUtils from '@libs/ValidationUtils'; import Visibility from '@libs/Visibility'; import stylePropTypes from '@styles/stylePropTypes'; import styles from '@styles/styles'; @@ -121,24 +121,6 @@ function Form(props) { const hasServerError = useMemo(() => Boolean(props.formState) && !_.isEmpty(props.formState.errors), [props.formState]); - /** - * This function is used to remove invisible characters from strings before validation and submission. - * - * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} - * @returns {Object} - An object containing the processed values of each inputID - */ - const prepareValues = useCallback((values) => { - const trimmedStringValues = {}; - _.each(values, (inputValue, inputID) => { - if (_.isString(inputValue)) { - trimmedStringValues[inputID] = StringUtils.removeInvisibleCharacters(inputValue); - } else { - trimmedStringValues[inputID] = inputValue; - } - }); - return trimmedStringValues; - }, []); - /** * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} * @returns {Object} - An object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2} @@ -146,7 +128,7 @@ function Form(props) { const onValidate = useCallback( (values, shouldClearServerError = true) => { // Trim all string values - const trimmedStringValues = prepareValues(values); + const trimmedStringValues = ValidationUtils.prepareValues(values); if (shouldClearServerError) { FormActions.setErrors(props.formID, null); @@ -204,7 +186,7 @@ function Form(props) { return touchedInputErrors; }, - [prepareValues, props.formID, validate, errors], + [props.formID, validate, errors], ); useEffect(() => { @@ -242,7 +224,7 @@ function Form(props) { } // Trim all string values - const trimmedStringValues = prepareValues(inputValues); + const trimmedStringValues = ValidationUtils.prepareValues(inputValues); // Touches all form inputs so we can validate the entire form _.each(inputRefs.current, (inputRef, inputID) => (touchedInputs.current[inputID] = true)); @@ -259,7 +241,7 @@ function Form(props) { // Call submit handler onSubmit(trimmedStringValues); - }, [props.formState.isLoading, props.network.isOffline, props.enabledWhenOffline, prepareValues, inputValues, onValidate, onSubmit]); + }, [props.formState.isLoading, props.network.isOffline, props.enabledWhenOffline, inputValues, onValidate, onSubmit]); /** * Loops over Form's children and automatically supplies Form props to them diff --git a/src/components/Form/FormProvider.js b/src/components/Form/FormProvider.js index 10ae32feedbe..fa0cc3ebd723 100644 --- a/src/components/Form/FormProvider.js +++ b/src/components/Form/FormProvider.js @@ -6,7 +6,7 @@ import _ from 'underscore'; import networkPropTypes from '@components/networkPropTypes'; import {withNetwork} from '@components/OnyxProvider'; import compose from '@libs/compose'; -import StringUtils from '@libs/StringUtils'; +import * as ValidationUtils from '@libs/ValidationUtils'; import Visibility from '@libs/Visibility'; import stylePropTypes from '@styles/stylePropTypes'; import * as FormActions from '@userActions/FormActions'; @@ -107,27 +107,9 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC const [errors, setErrors] = useState({}); const hasServerError = useMemo(() => Boolean(formState) && !_.isEmpty(formState.errors), [formState]); - /** - * This function is used to remove invisible characters from strings before validation and submission. - * - * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} - * @returns {Object} - An object containing the processed values of each inputID - */ - const prepareValues = useCallback((values) => { - const trimmedStringValues = {}; - _.each(values, (inputValue, inputID) => { - if (_.isString(inputValue)) { - trimmedStringValues[inputID] = StringUtils.removeInvisibleCharacters(inputValue); - } else { - trimmedStringValues[inputID] = inputValue; - } - }); - return trimmedStringValues; - }, []); - const onValidate = useCallback( (values, shouldClearServerError = true) => { - const trimmedStringValues = prepareValues(values); + const trimmedStringValues = ValidationUtils.prepareValues(values); if (shouldClearServerError) { FormActions.setErrors(formID, null); @@ -179,7 +161,7 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC return touchedInputErrors; }, - [errors, formID, prepareValues, validate], + [errors, formID, validate], ); /** @@ -199,7 +181,7 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC } // Prepare values before submitting - const trimmedStringValues = prepareValues(inputValues); + const trimmedStringValues = ValidationUtils.prepareValues(inputValues); // Touches all form inputs so we can validate the entire form _.each(inputRefs.current, (inputRef, inputID) => (touchedInputs.current[inputID] = true)); @@ -215,7 +197,7 @@ function FormProvider({validate, formID, shouldValidateOnBlur, shouldValidateOnC } onSubmit(trimmedStringValues); - }, [enabledWhenOffline, formState.isLoading, inputValues, network.isOffline, onSubmit, onValidate, prepareValues]); + }, [enabledWhenOffline, formState.isLoading, inputValues, network.isOffline, onSubmit, onValidate]); const registerInput = useCallback( (inputID, propsToParse = {}) => { diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 6c9b3463ca72..7c49006c10a5 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -353,6 +353,25 @@ function isValidAccountRoute(accountID: number): boolean { return CONST.REGEX.NUMBER.test(String(accountID)) && accountID > 0; } +type ValuesType = Record; + +/** + * This function is used to remove invisible characters from strings before validation and submission. + */ +function prepareValues(values: ValuesType): ValuesType { + const trimmedStringValues: ValuesType = {}; + + for (const [inputID, inputValue] of Object.entries(values)) { + if (typeof inputValue === 'string') { + trimmedStringValues[inputID] = StringUtils.removeInvisibleCharacters(inputValue); + } else { + trimmedStringValues[inputID] = inputValue; + } + } + + return trimmedStringValues; +} + export { meetsMinimumAgeRequirement, meetsMaximumAgeRequirement, @@ -386,4 +405,5 @@ export { isNumeric, isValidAccountRoute, isValidRecoveryCode, + prepareValues, };