import { FieldProps } from 'formik' import React, { useCallback, useState } from 'react' /** * Wraps a formik field component transforming the value in and out. * @param inputComponent The component to wrap * @param outerToInner * @param innerToOuter */ export function formikFieldTransformer<Props extends FieldProps<string>>( // eslint-disable-next-line @typescript-eslint/naming-convention InputComponent: React.ComponentType<Props>, outerToInner: (outerValue: string) => string, innerToOuter: (innerValue: string) => string, ): React.ElementType { return (props: Props) => { const { form: { setFieldValue }, field: { name, value: outerValue }, } = props // This smoothes things out and allows decimal points etc // (Allowing many-to-one of inner to outer) const [lastInnerValue, setLastInnerValue] = useState<string>(outerToInner(outerValue)) const value = outerValue === innerToOuter(lastInnerValue) ? lastInnerValue : outerToInner(outerValue) const onChange = useCallback( (event: React.ChangeEvent<HTMLInputElement>) => { setLastInnerValue(event.target.value) setFieldValue(name, innerToOuter(event.target.value)) }, [setFieldValue, name], ) return <InputComponent {...props} {...{ onChange, value }} /> } }