使用formik时,将抽象用于表单字段

发布于 2025-02-02 12:23:08 字数 904 浏览 1 评论 0 原文

我正在使用 formik 作为处理形式数据的库。

对于某些字段,我想使用不同的基础类型,例如我使用用于处理小数值*。

因此,以我的形式值,我希望我的小数类型以这种类型的代表。但是,当用户打字时,它仍应将输入视为字符串而不是数字。一个经典的示例是,如果用户想将“ 1000”更改为“ 2000”,如果他们删除“ 1”并输入“ 2”,则值将变为“ 20”,如果输入在键入过程中被视为数字。

我们还需要处理用户的语言环境(该语言环境取决于用户是租户的国家,而不是浏览器设置的成员)。

因此,当加载表单时,我需要将小数转换为局部字符串。 当我提交表格时,我需要在用户的语言环境中解析字符串,不是微不足道的<< /a>。

还有一些因字段,例如我有一个数量和数量字段 - 我们将总数计算为数量*量(使用Depimal.js)。因此,现在我已经有了局部解析3个不同位置的规则,在提交,验证输入时以及计算总数时。

是否有Formik的模式用于处理您正在使用的数据类型的不同基本抽象?

*我们使用DECIMAL.JS,因为JavaScript无法处理小数精度,例如0.1+0.2不等于0.3。对于许多情况,这并不重要,但是在我的应用中,我需要小数点精度。

I am using formik as a library to handle form data.

For some fields, I would like to use a different underlying type, e.g. I use decimal.js-light for handling of decimal values*.

So in my form values, I'd like my decimal types to be represented by this type. However, when the user is typing, it should still treat the input as string rather than a number. A classic example is if the user wants to change "1000" to "2000", if they delete the "1" and enter a "2", the value would become "20", if the input is treated as a number during typing.

We also need to handle the user's locale (the locale depends on the country of the tenant that the user is a member of, not the browser settings).

So when the form is loaded, I need to convert the decimal to a localized string.
When I submit the form, I need parse the string in the user's locale, which is not trivial.

There are also some dependent fields, e.g. I have a quantity and amount field - and we calculate the a total as quantity*amount (using decimal.js). So now I have the rules for localized parsing 3 different places, when submitting, when validating input, and when calculating the total.

Are there patterns for formik for dealing with a different underlying abstraction of the type of data you're working with?

* We use decimal.js because JavaScript doesn't handle decimal precision, e.g. 0.1+0.2 does not equal 0.3. For many scenarios this doesn't matter, but in my application, I need decimal precision.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月下凄凉 2025-02-09 12:23:08

因此,最后,我们确实有3组数据类型:

  • 我们从服务器获得的数字,并且应该保存(如果需要高精度保存,则以数字或字符串格式保存)
  • form> form> formik < /code>类型的字段<代码>十进制
  • 和为最终用户表示的格式字符串。

数据的表示可以轻松提取到单独的封装层。

Formik的字段参数之一 - IS 组件。您可以使用它来创建一个单独的组件,该组件只能使用字段值播放,将其按原样格式化,并将其显示给最终用户。因此,格式的值只能在该组件内生活。它不会在外面暴露。有一个漂亮的库( react-number-format )它以一种精致的方式。

它可能如以下内容完成:

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 */}
    />
  )
}

如果使用材料UI,其 textInput 组件还具有prop 组件,您可以通过自定义装饰器或使用现有解决方案 react-number-format 。我想您应该期望处理的所有案件。文档非常详尽。

这意味着,您不需要管理格式化数据的实际状态,您所要做的就是提供一些配置。

字符串本地化也将是该装饰器组件的责任。

之后 - 我们将在 formik s上下文中具有原始值。而且,所有剩下的就是写一些映射器,以将数字转换为 DECIMAL s,并将其作为 form> formik ,反之亦然。 - 映射十进制 s到 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
}

So, in the end, we do have 3 sets of data types:

  • numbers that we get from the server and that should be saved (either in number or string format if it is required to be saved with high precision)
  • formiks fields of type Decimal
  • and, formatted strings to be represented to the end user.

Representation of the data can be easily extracted to the separate encapsulated layer.

One of the formik's Field arguments - is component. You can use it to create a separate component that will play only with the field value, format it as it should be, and show it to the end user. So, the formatted value will live only inside that component. It would not be exposed outside. There is a pretty library(react-number-format) that can deal with it in a sophisticated way.

It may be done like the following:

import NumberFormat from 'react-number-format'
import { Field } from 'formik'

const FormattedPrice = () => {
  return <Field component={NumberFormat} thousandSeparator="," {/* ...otherProps */} />
}

or:

import NumberFormat from 'react-number-format'
import { useField } from 'formik'

const FormattedPrice2 = () => {
  const [{value}] = useField('price')

  return (
    <NumberFormat
      thousandSeparator=","
      prefix="
quot;
      value={value}
      {/* ...otherProps */}
    />
  )
}

If you use material UI, its TextInput component also has a prop component where you can pass your custom decorator or use an existing solution of react-number-format. I guess there should be all cases handled that you may expect to have. And documentation is pretty exhaustive.

It means, that you don't need to manage the actual state of formatted data, all you have to do - is provide some configuration.

String localization would also be the responsibility of that decorator component.

After this - we will have raw values in our formiks context. And, all that is left - is to write some mappers to convert numbers to Decimals and provider them as an initialValues to formik and vice versa - map Decimals to numbers somewhere in the onSubmit after data is validated. That part may be extracted to separate helper class to handle all in one place and make his functions self-annihilating. The approximate interface of that class:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文