mantine
mantine copied to clipboard
form.watch doesn't work with arrays
Dependencies check up
- [X] I have verified that I use latest version of all @mantine/* packages
What version of @mantine/* packages do you have in package.json?
7.13.2
What package has an issue?
@mantine/form
What framework do you use?
Vite
In which browsers you can reproduce the issue?
All
Describe the bug
Shopping cart scenario - we have few items with prices, we can change amount of items in that shopping cart and we wanna display total value.
When we use "uncontrolled" form, we should use form.watch to track specific values.
Our products form field is an array [{ name: "phone", price: 1000, numberOfUnits: 1}].
When we use form.watch("products", console.log) nothing is happening.
I found that previously it was mentioned as "not planned" https://github.com/mantinedev/mantine/issues/6280#issuecomment-2128795340
Currently if I want to track this, I had to use use-force-update hook and force rerender on onChange of numberOfUnits
I wanted to ask if we could revisit thinking about this issue or maybe there is different workaround to this.
If possible, include a link to a codesandbox with a minimal reproduction
No response
Possible fix
No response
Self-service
- [ ] I would be willing to implement a fix for this issue
@jrozbicki I worked around this by calling setFieldValue for the array fields after reset. This way form.watch('products', ... gets triggered. Maybe It is a good idea for watch docs to be updated
const handleFormReset = () => {
form.setFieldValue('products', []); <-- call this first to get correct previousValue in watch callback
form.reset();
};
i'm using v8+ and running into the same issue. would love to see arrays added to form.watch() since the ability to have arrays in forms, but not being able to detect changes feels like giving a fireman a hose but then not hooking it up to a water tank..."thanks, but not really useful"
here's my approach to a workaround...leverage React state, the onValuesChange function, and, in this case, a reduce function:
type Product = {name: string, price: number, numberOfUnits: number}
const [productTotal, setProductTotal] = useState(0)
const form = useForm({
mode: 'uncontrolled',
initialValues: {
products: [],
},
onValuesChange: (values) => {
const { products} = values ?? []
const calcProductTotal= products.reduce((acc, i)=>(acc + i.number * i.numberOfUnits),0)
console.log("products total: ", calcProductTotal)
setProductTotal(calcProductTotal)
},
})