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

React FormIK实现依赖字段计算时报textB.trim is not a function错误如何解决

报错根因

你在执行setFieldValue(props.name, textA/textB)时,给字段赋值的是数字类型的值,但初始值为字符串,后续useEffect触发时直接对已经变成数字的字段调用.trim()方法,数字不存在该方法,因此抛出TypeError: textB.trim is not a function。
除此之外你的代码还存在两处逻辑错误:

  • MyFieldA组件的计算逻辑错误:根据textB、textC反推textA的公式应为textA = textB * textC,你写的还是textA/textB,同时touched判断条件错误,应校验textB和textC是否被触碰,不是textA
  • 没有做边界校验:未处理非数字输入、除以0的场景,也没有判断目标字段是否已被用户手动填写,容易覆盖用户输入

修复方案

统一先把字段值转为字符串后再做非空校验,修正三个字段的计算逻辑和判断条件,增加边界处理和用户手动输入的优先级判断,修复后的完整代码如下:

import React from 'react';
import { Formik, Form, useFormikContext, useField } from 'formik';

const MyFieldC = (props) => {
  const {
    values: { textA, textB },
    touched,
    setFieldValue,
  } = useFormikContext();
  const [field, meta] = useField(props);

  React.useEffect(() => {
    // 先转字符串判断非空,且当前字段未被用户手动填写时才自动赋值
    const aStr = String(textA).trim();
    const bStr = String(textB).trim();
    if (
      aStr && bStr &&
      touched.textA && touched.textB &&
      !touched[props.name] // 避免覆盖用户手动输入的C值
    ) {
      const a = Number(aStr);
      const b = Number(bStr);
      if (!isNaN(a) && !isNaN(b) && b !== 0) {
        setFieldValue(props.name, a / b);
      }
    }
  }, [textB, textA, touched.textA, touched.textB, touched[props.name], setFieldValue, props.name]);

  return (
    <>
      <input {...props} {...field} />
      {!!meta.touched && !!meta.error && <div>{meta.error}</div>}
    </>
  );
};

const MyFieldA = (props) => {
  const {
    values: { textC, textB },
    touched,
    setFieldValue,
  } = useFormikContext();
  const [field, meta] = useField(props);

  React.useEffect(() => {
    const cStr = String(textC).trim();
    const bStr = String(textB).trim();
    if (
      cStr && bStr &&
      touched.textC && touched.textB &&
      !touched[props.name] // 避免覆盖用户手动输入的A值
    ) {
      const c = Number(cStr);
      const b = Number(bStr);
      if (!isNaN(c) && !isNaN(b)) {
        setFieldValue(props.name, b * c);
      }
    }
  }, [textB, textC, touched.textC, touched.textB, touched[props.name], setFieldValue, props.name]);

  return (
    <>
      <input {...props} {...field} />
      {!!meta.touched && !!meta.error && <div>{meta.error}</div>}
    </>
  );
};

const MyFieldB = (props) => {
  const {
    values: { textA, textC },
    touched,
    setFieldValue,
  } = useFormikContext();
  const [field, meta] = useField(props);

  React.useEffect(() => {
    const aStr = String(textA).trim();
    const cStr = String(textC).trim();
    if (
      aStr && cStr &&
      touched.textA && touched.textC &&
      !touched[props.name] // 避免覆盖用户手动输入的B值
    ) {
      const a = Number(aStr);
      const c = Number(cStr);
      if (!isNaN(a) && !isNaN(c) && c !== 0) {
        setFieldValue(props.name, a / c);
      }
    }
  }, [textC, textA, touched.textA, touched.textC, touched[props.name], setFieldValue, props.name]);

  return (
    <>
      <input {...props} {...field} />
      {!!meta.touched && !!meta.error && <div>{meta.error}</div>}
    </>
  );
};

function Form() {
  const initialValues = { textA: '', textB: '', textC: '' };
  return (
    <div className="App">
      <Formik
        initialValues={initialValues}
        onSubmit={async (values) => alert(JSON.stringify(values, null, 2))}
      >
        <div className="section">
          <Form>
            <label>
              FieldA
              <MyFieldA name="textA" type="number" />
            </label>
            <label>
              FieldB
              <MyFieldB name="textB" type="number" />
            </label>
            <label>
              FieldC
              <MyFieldC name="textC" type="number" />
            </label>
            <button type="submit">Submit</button>
          </Form>
        </div>
      </Formik>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:06:02