mantine icon indicating copy to clipboard operation
mantine copied to clipboard

form.watch doesn't work with arrays

Open jrozbicki opened this issue 1 year ago • 1 comments

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.

image image

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 avatar Oct 18 '24 15:10 jrozbicki

@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();
  };

yshterev avatar Oct 30 '24 10:10 yshterev

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)
		},
	})

btroop avatar Jul 24 '25 17:07 btroop