【问题标题】:Using setFieldValue for one field, based on another filed values根据另一个字段值对一个字段使用 set Field Value
【发布时间】:2020-01-24 08:00:03
【问题描述】:

我正在使用 formik react 库并尝试根据另一个的 onChange 事件更新 2 个字段。例如,

price = quantity * totalPrice

price :
onChange={() => {setFieldValue('quantity',values.quantity? values.price / values.totalPrice:values.quantity, );
setFieldValue('totalPrice',values.totalPrice? values.price * values.quantity: values.totalPrice,);}}

quantity :
onChange={(value, e) => { this.disableFiled(value, e); setFieldValue('totalPrice',values.price ? values.price * values.totalPrice : ' ',);}}

totalPrice:
onChange={(value, e) => { this.disableFiled(value, e);setFieldValue('quantity',values.price ? values.totalPrice / price : ' ', ); }}

当数量有值时,总价将被禁用,反之亦然。但它不会正确计算其他字段

【问题讨论】:

    标签: javascript reactjs forms formik


    【解决方案1】:

    我就是这样做的。

    App.js 文件:

    import React from "react";
    import "./styles.css";
    import { Formik } from "formik";
    import * as Yup from "yup";
    import CalculatedField from "./CalculatedField";
    
    const App = () => (
      <div className="app">
        <Formik
          initialValues={{ price: "", quantity: "", totalPrice: "" }}
          onSubmit={async values => {
            await new Promise(resolve => setTimeout(resolve, 500));
            alert(JSON.stringify(values, null, 2));
          }}
          validationSchema={Yup.object().shape({
            price: Yup.number("It's a number").required("Required"),
            quantity: Yup.number("It's a number").required("Required"),
            totalPrice: Yup.number("It's a number").required("Required")
          })}
        >
          {props => {
            const {
              values,
              touched,
              errors,
              isSubmitting,
              handleChange,
              handleBlur,
              handleSubmit,
              setFieldValue
            } = props;
            return (
              <form onSubmit={handleSubmit}>
                <div className="input-row">
                  <label htmlFor="quantity" style={{ display: "block" }}>
                    Quantity
                  </label>
                  <input
                    id="quantity"
                    name="quantity"
                    placeholder="Enter quantity"
                    type="number"
                    value={values.quantity}
                    onChange={handleChange}
                    onBlur={handleBlur}
                    className={
                      errors.quantity && touched.quantity
                        ? "text-input error"
                        : "text-input"
                    }
                  />
                  {errors.quantity && touched.quantity && (
                    <div className="input-feedback">{errors.quantity}</div>
                  )}
                </div>
                <div className="input-row">
                  <label htmlFor="price" style={{ display: "block" }}>
                    Price
                  </label>
                  <input
                    id="price"
                    name="price"
                    placeholder="Enter your price"
                    type="number"
                    value={values.price}
                    onChange={handleChange}
                    onBlur={handleBlur}
                    className={
                      errors.price && touched.price
                        ? "text-input error"
                        : "text-input"
                    }
                  />
                  {errors.price && touched.price && (
                    <div className="input-feedback">{errors.price}</div>
                  )}
                </div>
    
                <div className="input-row">
                  <label htmlFor="totalPrice" style={{ display: "block" }}>
                    Total Price
                  </label>
                  <CalculatedField
                    id="totalPrice"
                    type="number"
                    name="totalPrice"
                    value={values.totalPrice}
                    values={values}
                    setFieldValue={setFieldValue}
                    onChange={handleChange}
                    onBlur={handleBlur}
                    className={
                      errors.totalPrice && touched.totalPrice
                        ? "text-input error"
                        : "text-input"
                    }
                  />
                  {errors.totalPrice && touched.totalPrice && (
                    <div className="input-feedback">{errors.totalPrice}</div>
                  )}
                </div>
    
                <div className="input-row">
                  <button type="submit" disabled={isSubmitting}>
                    Submit
                  </button>
                </div>
              </form>
            );
          }}
        </Formik>
      </div>
    );
    export default App;
    

    CalculatedField.js

    import React, { useEffect } from "react";
    
    const CalculatedField = props => {
      useEffect(() => {
        var val = 0;
        if (props.values.price && props.values.quantity) {
          val = props.values.price * props.values.quantity;
        }
        props.setFieldValue("totalPrice", val);
      }, [props.values]);
    
      return (
        <input
          id="totalPrice"
          type="number"
          name="totalPrice"
          value={props.values.totalPrice}
        />
      );
    };
    
    export default CalculatedField;
    

    这基本上是通过在 CalculatedField 组件的 useEffect 挂钩中调用 setFieldValue 方法来实现的。请记住 useEffect 会观察值的变化并在它们被修改时运行 setFieldValue 方法。

    请关注 CodeSandbox 演示。 https://codesandbox.io/s/affectionate-mirzakhani-who30?file=/src/App.js

    【讨论】:

    • 感谢 Choudbury,它对我帮助很大!
    • 如果有数组的输入,如&lt;FieldArray /&gt;,如何获取这个CalculateField
    【解决方案2】:

    看看这个可能会有所帮助:

    https://github.com/jaredpalmer/formik/issues/1840

    您必须致电handleChange(e)现场更改!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 1970-01-01
      • 2022-07-20
      相关资源
      最近更新 更多