Open mauricedb opened 5 years ago
Interesting idea. This is effectively another approach to #812. applyBusinessRules is really just a state reducer.
Going to mark as a duplicate.
I would mention #401 as well here...
@jaredpalmer Didn't want to call it a reducer because of the slightly different signature but making this a proper reducer makes a lot of sense to me. It makes it easy to differentiate between updates coming from setValues()
or setFieldValue()
.
The basic signature could look something like:
type ReducerAction<Values> = {
type: "setFieldValue";
payload: {
field: string;
value: any;
};
}
| {
type: "setValues";
payload: Partial<Values>;
};
export class Formik<Values>
reducer = (values: Values, action: ReducerAction<Values>): Values => {
return values;
};
// Other code
}
With a Values definition of:
type Shape = {
shape: string;
width: number;
height: number;
};
The complete reducer for the business rule above would look something like:
const reducer = (values: Shape, action: ReducerAction<Shape>): Shape => {
if (action.type === "setFieldValue") {
const { field, value } = action.payload;
if (values.shape === "square") {
switch (field) {
case "width":
return { ...values, height: value };
case "height":
return { ...values, width: value };
}
} else if (field === "shape" && value === "square") {
return { ...values, width: values.height };
}
} else {
const { shape, height } = action.payload;
if (shape === "square") {
return { ...values, width: height };
}
}
return values;
};
And a nice side benefit of this approach is the possibility to wire up and be able to track changes to values
using the Redux Devtools.
Closing as duplicate and stale
@maddhruv interestingly, this issue has never been solved so I would leave it open. A few proposals have been made. All issues this is mentioned as being a duplicate of are closed.
Formik.onChange
prop described here. This would be so easy to implement, but it would be hard to cover all users' cases. I think this one would be specifically for values
and not necessarily onStateChange
, which would be better suited to the reducer technique.FormikReducer
described here and here and here, allowing devs to use a redux-like reducer to subscribe to changes in formik.values
. This would be one of the largest expansions to customizability we could probably give to Formik.useEffect
, and document that it will be the only supported method.Also discussed here: https://github.com/formium/formik/discussions/2474
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 60 days
🚀 Feature request
Current Behavior
At the moment form validation can be done by using the
validate
orvalidationSchema
props on theFormik
component. However it isn't possible to apply other business logic at the same central place. Instead if one value needs to be updated when another value changes this has to be coded up using a custom component andsetFieldValue
calls. This leads to business logic spread out and intertwined with UI logic. An example would be a component like this to keep width and height the same if the shape is a square:Desired Behavior
A much better approach would be to centralize this logic at the
Formik
level, just like validation and keep it out of the UI logic.Suggested Solution
A much better approach would be to add a callback to the
Formik
component to run after each change and be able to apply any business rules.And then wire up the business logic as follows:
The default of
applyBusinessRules
would be to just leave thevalues
as they where.Who does this impact? Who is this for?
This would be a useful feature for every developer creating complex forms with business rules that update other values based on changes a user makes.
Describe alternatives you've considered
Additional context
Martin Fowler on separating UI code