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
相关产品推荐
相关产品推荐

