You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React-Final-Form中基于表单数据条件格式化值?

解决React Final Form中动态货币格式化的问题

我太懂这个痛点了——React Final Form默认的字段format函数只能拿到当前字段的值,没法直接访问表单里其他字段的内容,比如你需要动态切换的货币类型。这里有两个实用的解决方案,帮你优雅搞定这个需求:

方案一:用FormSpy传递货币类型到自定义输入组件

这个方法通过FormSpy监听表单值的变化,把货币类型字段的值传递给自定义的货币输入组件,在组件内部完成格式化和解析:

首先定义一个自定义的货币输入组件:

import { Field } from 'react-final-form';

const CustomCurrencyInput = ({ input, meta, currency }) => {
  // 格式化函数:根据传入的货币类型生成对应格式
  const formatMoney = (value) => {
    if (!value) return value;
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      minimumFractionDigits: 2,
      currency: currency || 'USD'
    }).format(value);
  };

  // 解析函数:把用户输入的货币字符串转成数字(存到表单值里)
  const parseMoney = (value) => {
    if (!value) return value;
    // 去掉货币符号、逗号等非数字字符,转成浮点数
    return parseFloat(value.replace(/[^0-9.-]/g, ''));
  };

  return (
    <input
      {...input}
      type="text"
      value={formatMoney(input.value)}
      onChange={(e) => input.onChange(parseMoney(e.target.value))}
    />
  );
};

然后在表单中使用FormSpy和这个组件:

import { Form, Field, FormSpy } from 'react-final-form';

const MyForm = () => {
  return (
    <Form
      onSubmit={(values) => console.log('提交的值:', values)}
      initialValues={{ amount: 0, currency: 'USD' }}
      render={({ handleSubmit }) => (
        <form onSubmit={handleSubmit}>
          {/* 货币类型选择器 */}
          <Field name="currency" component="select">
            <option value="USD">美元 (USD)</option>
            <option value="EUR">欧元 (EUR)</option>
            <option value="GBP">英镑 (GBP)</option>
          </Field>

          {/* 用FormSpy订阅表单值变化,传递currency给金额字段 */}
          <FormSpy subscription={{ values: true }}>
            {({ values }) => (
              <Field
                name="amount"
                component={CustomCurrencyInput}
                currency={values.currency}
              />
            )}
          </FormSpy>

          <button type="submit">提交</button>
        </form>
      )}
    />
  );
};

方案二:用useForm Hook直接访问表单值

如果你用的是函数组件,useForm Hook能让你直接获取表单的所有值,这样就能在format函数里动态使用货币类型:

import { Form, Field, useForm } from 'react-final-form';

const AmountField = () => {
  // 通过useForm获取当前表单的所有值
  const { values } = useForm();
  const currentCurrency = values?.currency || 'USD';

  const formatMoney = (value) => {
    if (!value) return value;
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      minimumFractionDigits: 2,
      currency: currentCurrency
    }).format(value);
  };

  const parseMoney = (value) => {
    if (!value) return value;
    return parseFloat(value.replace(/[^0-9.-]/g, ''));
  };

  return (
    <Field
      name="amount"
      format={formatMoney}
      parse={parseMoney}
      component="input"
      type="text"
    />
  );
};

// 在表单中使用这个自定义字段组件
const MyForm = () => {
  return (
    <Form
      onSubmit={(values) => console.log('提交的值:', values)}
      initialValues={{ amount: 0, currency: 'USD' }}
      render={({ handleSubmit }) => (
        <form onSubmit={handleSubmit}>
          <Field name="currency" component="select">
            <option value="USD">美元 (USD)</option>
            <option value="EUR">欧元 (EUR)</option>
            <option value="GBP">英镑 (GBP)</option>
          </Field>

          <AmountField />

          <button type="submit">提交</button>
        </form>
      )}
    />
  );
};

关键提醒:不要忽略parse函数

不管用哪种方案,都必须实现parse函数——因为用户输入的是带货币符号、千分位逗号的字符串,我们需要把它转成纯数字才能正确存在表单的values里,否则提交的会是字符串而不是数字类型的金额。

内容的提问来源于stack exchange,提问作者sww314

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:01:14