Open rahi-nz opened 5 years ago
@rahi-nz Could you kindly format your code? It is very hard to read.
I stumbled upon this issue when researching whether there is a more elegant solution than ours. This is what we did (pseudo-code):
onChange={(e) => {
formikProps.handleChange(e);
formikProps.values.dependentValue = calcDependent(e.target.value);
}}
I find this rather disturbing, but we could not think of a better way to do it. Can you, @jaredpalmer?
I find the above disturbing because
e.target.value
)@rahi-nz Could you kindly format your code? It is very hard to read.
I stumbled upon this issue when researching whether there is a more elegant solution than ours. This is what we did (pseudo-code):
onChange={(e) => { formikProps.handleChange(e); formikProps.values.dependentValue = calcDependent(e.target.value); }}
I find this rather disturbing, but we could not think of a better way to do it. Can you, @jaredpalmer?
I find the above disturbing because
- it throws the abstraction that Formik provides out of the window (
e.target.value
)- it modifies the state of something that does not have a specified API. Not only is this hacky, but it might also stop working with any release.
Thanks @alexbepple It worked like a charm I use it like this :
you should use setFieldValue to update values, may something like
onChange={(e) => { formikProps.handleChange(e); formikProps.setFieldValue('dependentValue',calcDependent(e.target.value)); }}
you should use setFieldValue to update values, may something like
onChange={(e) => { formikProps.handleChange(e); formikProps.setFieldValue('dependentValue',calcDependent(e.target.value)); }}
setFieldValue is an event callback that only updates the ref after each render so it doesn't work because every time return previous value in others field.
alexbepple's way works well:
onChange={(e) => { formikProps.handleChange(e); formikProps.values.dependentValue = calcDependent(e.target.value); }}
You can also use an effect and a child component. Theres been some discussion of change listeners but we haven't found the ideal API for it yet.
In child component: (apologies for mobile formatting)
const formik = useFormikContext();
React.useEffect(() =>
formik.setFieldValue("dependentField", calculateDependentValue(formik.values.mainField);
}, [formik.values.mainField]);
Pros are a more decentralized approach, cons are extra components and a render where they aren't in sync.
I'd recommend against changing properties directly on formik.values! Treat it as an immutable object.
We ended up doing something slightly more kosher than what I outlined above. onChange
we calculate the entire new data structure representing the form. Pseudo code: onChange={e => formik.setValues(updateAllDependentFormValues(e.target.value, formik.values))}
.
It's a bit strange that setFieldValue
behaves differently from setValues
(at least in version 1.4.1).
However, we are generally fairly happy with this approach because
setValues
) instead of hackily modifying formik.values
directly/cc @alexkolson
We ended up doing something slightly more kosher than what I outlined above.
onChange
we calculate the entire new data structure representing the form. Pseudo code:onChange={e => formik.setValues(updateAllDependentFormValues(e.target.value, formik.values))}
.It's a bit strange that
setFieldValue
behaves differently fromsetValues
(at least in version 1.4.1).However, we are generally fairly happy with this approach because
- it uses the API (
setValues
) instead of hackily modifyingformik.values
directly- this approach led us to separating the form logic (data structure + operations on this structure) from the presentation
/cc @alexkolson
but can i do this with an array / objects nested values?
@ahmad-reza619 yes, though I'm not sure how I can explain further without an example. All you're doing is changing your entire values object, and given the name and value of an input and the previous values you should be able to do that. Example:
// getIn and setIn are helpers exported from Formik which get and set values in complex objects,
// returns a new object if setIn causes a change
// example field names for brevity
const updateAllDependentValues = (name = "myObj.myField", value, prevValues) => {
let newValues = setIn(prevValues, name, value);
if (getIn(prevValues, name) !== getIn(newValues, name)) {
// value changed, set other values
newValues = setIn(newValues, "myObj.otherField", calculateOtherValue(value);
}
return newValues;
}
In my own case, I handled the situation by creating a function like below
const handleAgeChange = (handler) => (e) => {
const { target } = e;
const { value } = target;
const computedValue = computeDependentValue(value);
handler({ target });
// computedInputName is the value of the name attribute of the input whose value is to be computed
handler({ target: { name: 'computedInputName', value: computedValue } });
};
Then for the onChange
attribute of the input I pass in as below
onChange={handleAgeChange(handleChange)} // passing in formik's own handleChange as the handler
I came across the same problem. I’ve been able to update the field values state by mapping through the independent options and setting a state variable based on the option selected. Ex:
setIndependentStateVariable((prevData)=>({…prevData, key: yourInitialValuesName.value})
// map through the state variable and filter the values you need const dependentOptions = independentStateVaribale.filter(item=>({relevant code}))
// map through the filtered array. Check if filtered array is not undefined. I used conditional rendering with a ternary.
// also make sure to set the name in the select options to the name of the initial values with the current index.
I hope this helps someone!
I did the update in the submit, assigning the value like this
<Formik
onSubmit={async (values, actions) => {
values.numite=values.candet;
values.totdet=values.candet*values.valuni;
}
>
❓Question
I'm using formik react library and trying to update 2 fields, based on the onChange event of anothers. For example,
price :
quantity :
totalPrice:
when quantity has value total price will be disabled and vice versa.but it doesn't calculate other fields correctly