You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First of all, a round of praise and gratitude for @tanstack/form - what a beautiful API and great performance! Much easier to reason about and build with than my previous experiences with formik, react-hook-form and uniforms ✨
I'm building a fully-fledged schema-driven form builder on top of @tanstack/react-form for a project with dozens of forms. In the process, I came across the use-case of changing the value of one field based on another's update. Currently, I'm using a form.Subscribe to listen to other fields' values and an useEffect to set the field's value, if it's not yet set:
<form.Subscribekey={name}selector={(state)=>[subscribe.selector(state),getBy(state.values,name)]asconst}>{([selected,fieldValue])=>{constresult=subscribe.result(selected,fieldValue)/** * This is not the ideal set-up, performance-wise, as we first update the linked field(s), * and then the subscriber. A better approach would be to modify the on change handlers * of the linked field(s) to update the subscriber in one go, in a single render. * * For simplicity's sake, let's stick with this - @tanstack/form doesn't have an * API to hook into changes and modify them (middleware pattern). */useEffect(()=>{if(result.newValue&&result.newValue!==fieldValue){// @ts-expect-error types can't reach this farprops.form.setFieldValue(name,result.newValue)}},[result.newValue])// rendering the actual field...
The issue, as the comment suggests, is that this pattern leads to 2 renders - one for when the linked field(s) change, another for when the subscribed field changes. It also feels brittle and not very elegant 😬
My suggestion would be to provide a changes middleware API, in which we can subscribe to changes in the form's values (scoped by sub-path?) and choose to modify it or not:
// pseudo-code for the middleware pattern// - could be used anywhere with access to the form // - the useMiddleware hook automatically cleans-up after itselfform.useMiddleware((updatedValue,prevValue)=>{// domain-specific logic for, say, changing `status` to `published` when `published_at` is set to the pastconstfieldModifications=myCustomMiddleware(updatedValue,prevValue)return{...updatedValue, ...(fieldModifications||{})}})
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
First of all, a round of praise and gratitude for @tanstack/form - what a beautiful API and great performance! Much easier to reason about and build with than my previous experiences with formik, react-hook-form and uniforms ✨
I'm building a fully-fledged schema-driven form builder on top of
@tanstack/react-form
for a project with dozens of forms. In the process, I came across the use-case of changing the value of one field based on another's update. Currently, I'm using aform.Subscribe
to listen to other fields' values and anuseEffect
to set the field's value, if it's not yet set:The issue, as the comment suggests, is that this pattern leads to 2 renders - one for when the linked field(s) change, another for when the subscribed field changes. It also feels brittle and not very elegant 😬
My suggestion would be to provide a changes middleware API, in which we can subscribe to changes in the form's values (scoped by sub-path?) and choose to modify it or not:
Beta Was this translation helpful? Give feedback.
All reactions