Using setFieldValue for one field, based on another filed values
13,747
Solution 1
Check this out it may help :
https://github.com/jaredpalmer/formik/issues/1840
you have to call handleChange(e)
on-field change!
Solution 2
This is how I do this.
App.js file:
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;
This is basically achieved by calling setFieldValue method within useEffect hooks in the CalculatedField component. Please remember useEffect will watch for the change of the values and run the setFieldValue method when they are modified.
Please follow the CodeSandbox demo. https://codesandbox.io/s/affectionate-mirzakhani-who30?file=/src/App.js
Author by
Rahele Nazari
Updated on June 26, 2022Comments
-
Rahele Nazari almost 2 years
I'm using formik react library and trying to update 2 fields, based on the onChange event of another. For example,
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 : ' ', ); }}
when quantity has value, total price will be disabled and vice versa.but it doesn't calculate other fields correctly
-
Kaherdin over 2 yearsThanks Choudbury, It helped me a lot !
-
rjcode over 2 yearsHow can you get this CalculateField, if there is the input of array, like
<FieldArray />