我使用formik作为一个库来处理表单数据。
对于某些字段,我希望使用不同的基础类型,例如,我使用decimal.js-light处理十进制值*。
因此,在我的表单值中,我希望用这个类型来表示我的十进制类型。但是,当用户输入时,它仍然应该将输入看作字符串而不是数字。一个典型的例子是,如果用户希望将"1000“更改为"2000",如果用户删除"1”并输入"2",则如果输入在输入时被视为数字,则该值将变为"20“。
我们还需要处理用户的区域设置(区域设置取决于用户所属的租户的国家,而不是浏览器设置)。
因此,在加载表单时,我需要将十进制转换为本地化字符串。当我提交表单时,我需要解析用户区域设置这并不是微不足道的中的字符串。
还有一些依赖的字段,例如,我有一个数量和数量字段-我们计算的总量为数量*数量(使用decimal.js)。因此,现在我有了本地化解析的规则,在提交、验证输入和计算总计时,都有三个不同的位置。
formik是否有处理您正在处理的数据类型的不同底层抽象的模式?
*我们使用decimal.js是因为JavaScript不处理十进制精度,例如0.1+0.2不等于0.3。对于许多情况,这并不重要,但在我的应用程序中,我需要十进制精度。
发布于 2022-07-28 20:56:54
最后,我们有三组数据类型:
formik的Decimal类型字段数据的表示可以很容易地提取到单独的封装层。
formik的Field参数之一是component。您可以使用它创建一个单独的组件,该组件只对字段值进行播放,将其格式化为应有的格式,并将其显示给最终用户。因此,格式化的值将只存在于该组件中。它不会暴露在外面。有一个漂亮的库(反应-数字格式)可以以复杂的方式处理它。
这样做的方式如下:
import NumberFormat from 'react-number-format'
import { Field } from 'formik'
const FormattedPrice = () => {
return <Field component={NumberFormat} thousandSeparator="," {/* ...otherProps */} />
}或者:
import NumberFormat from 'react-number-format'
import { useField } from 'formik'
const FormattedPrice2 = () => {
const [{value}] = useField('price')
return (
<NumberFormat
thousandSeparator=","
prefix="$"
value={value}
{/* ...otherProps */}
/>
)
}如果您使用material,那么它的TextInput组件也有一个支持component,您可以在这里传递自定义装饰器或使用现有的react-number-format解决方案。我想你应该会处理好所有的案子。文档是非常详尽的。
这意味着,您不需要管理格式化数据的实际状态,只需提供一些配置。
字符串本地化也是该装饰组件的责任。
在此之后,我们将在formik的上下文中获得原始值。剩下的就是编写一些映射器,将数字转换为Decimals,并将它们作为initialValues提供给formik,反之亦然--在验证数据之后,将Decimal映射到onSubmit中的某个位置。该部分可以提取为单独的助手类,以处理所有在一个地方,并使他的功能自我毁灭。该类的近似接口:
import Decimal from 'decimal.js-light'
type BackendResponseData = {
price: number
// other fields
}
type FormValues = {
price: Decimal
// other fields
}
interface DataConverter {
storedDataToFormValues(storedData: BackendResponseData) => FormValues
formValuesToStoredData(formValues: FormValues) => BackendResponseData
}https://stackoverflow.com/questions/72402215
复制相似问题