-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Form hook causes infinite re-render when using as required effect dependency #5338
Comments
Do not add |
While this the most obvious option, I am still confused why it does not make sense. As far as I understand the official documentation, every reactive value needs to be a declared dependency. But |
@rtivital Why does Actually,
What do you think about breaking down the result into 1) the handlers, which should (almost) never change, and 2) the values, which should change often? Then we could do something like: function useForm() {
const [values, setValues] = useState({})
const isDirty = useMemo(() => Object.keys(values).length > 0, [values])
const reset = useCallback(function () {
setValues({})
}, [])
const handlers = useMemo(
() => ({
setValues,
reset,
}),
[reset]
)
const observables = useMemo(
() => ({
values,
isDirty,
}),
[values, isDirty]
)
return useMemo(() => [handlers, observables] as const, [handlers, observables])
}
function Foo() {
const [formHandlers, formObservables] = useForm()
useEffect(
function () {
// Only runs when the handlers change (which is probably never)
},
[formHandlers]
)
useEffect(
function () {
// Only runs when the values change (which is probably often)
},
[formObservables]
)
return (
<>
<Button
onClick={function() {
formHandlers.setValues({ a: Math.random() })
}}
>
Change values
</Button>
<pre>{JSON.stringify(formObservables)}</pre>
</>
)
} This is essentially the same as writing Also, those who do not care about destructuring and just write Appreciate your feedback. 🙏 |
@rtivital How'd you feel about wrapping some more things in |
All form handlers are already wrapped in useCallback |
Nope, see e.g. getInputProps. |
I'm having the same problem here. I've already tried using In the local development environment I don't feel the slowness, but in the production environment there is a very large delay. Which ends up bothering the user when filling out the fields. In the video below, I even removed vokoscreen-2024-03-27_09-36-42.mp4const form = useForm<FormValues>({
initialValues: {
name: '',
email: '',
zip_code: '',
state: '',
city: '',
address: '',
number: '',
neighborhood: '',
complement: '',
latitude: '',
longitude: ''
},
validate: yupResolver(schema)
});
...
<Box
component="form"
onSubmit={form.onSubmit(onSubmit)}
className="space-y-2"
>
...
<TextInput
label="Nome"
placeholder="Nome"
{...form.getInputProps('name')}
/> Any solution? |
use-form stores values in state, it is expected behavior to rerender on each field change. If your app works correctly in development but worse in production, it is most likely not related to the form updating state. React heavily optimizes state changes in prod which results in exactly opposite – the same code works much faster in production. You can use a performance tab to find the code that causes the issue. |
Thank you for the response, @rtivital. In fact, I think Mantine is an incredible job 👏 But there is definitely something strange causing this rerender. For example, just for testing purposes, I used the vokoscreen-2024-03-27_14-13-20.mp4Anyway... I'm not sure if it's a problem with my application, but I haven't figured out what it could be yet. For now, I'll use Thanks! |
you can try smth like this const { setValues, ...form } = useForm({ initialValue })
useEffect(() => {
setValues(newData)
}, [newData, setValues]) |
I tried! But I got the same result :( |
I also ran into this issue just now and noticed that the const form = useForm<FormValues>({
mode: 'uncontrolled'
initialValues: {
name: '',
...
},
validate: yupResolver(schema)
}); |
Thank you for answer, but what's your version of the Mantine? Here I receive this error
I use version |
@nielsVoogt update my version to vokoscreen-2024-06-12_10-38-11.mp4My description field has stopped causing the rerender, but my value field still causes it. But it was a big step, thank you. |
I’m not sure if it’s an issue with React, but I often find myself struggling with the "exhaustive-deps" problem. Based on this demo for loading initial data (and many others):
The common practice is to avoid including If you also use ESLint with the "react-hooks/exhaustive-deps" rule, you’ll encounter this error:
As a result, developers often need to disable this line in the linting: useEffect(() => {
loadInitialValues().then((values) => {
form.setValues(values);
form.resetDirty(values);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); This is typically what I do because I know it’s safe. However, with the introduction of "react-compiler" recently, if you also use ESLint with "react-compiler/react-compiler", you’ll see this error:
Basically it means you won't benefit from react-compiler in this entrie component because you have disabled a React ESLint. Is this expected? I don't know. But maybe I should turn off these linters. Is the usage of @mantine/hooks incorrect? I don't know. But maybe -
mantine/packages/@docs/demos/src/demos/form/Form.demo.watch.tsx Lines 12 to 22 in fbcee92
Or perhaps it’s just the tricky UX patterns in React that leave every developer feeling puzzled from time to time. |
What package has an issue?
@mantine/form
Describe the bug
In the example of your docs (https://mantine.dev/form/recipes/#set-initial-values-with-async-request) you use the
useEffect
as a mount-only cycle.However, considering that I can have the form mounted and the actual values can change via props (or any other hook), I might want to extend the
useEffect
hook with other properties that change.Consider I want to change the values with an effect like this:
With the example above, eslint complains about the
form
object not being a dependency (which is technically correct, isn't it?). Now if I add the form object as a dependency (regardless of either usingform
directly or destructuringsetValues
andresetDirty
), I get an infinite render cycle:How do you explain the correct approach, re-rendering on single prop changes and update the values accordingly while still being linting-compatible? Our project follows pretty strict linting rules, so exclusions are not really possible here. Also I assume re-setting initial values as a "one-time-re-render" is not an option. Further I guess that the form relies on all components being controlled and therefore always re-renders on a change, whereas a
setValue
call is a reason here.Please give me some input on the technical correctness, and a working, linted code 🙏
What version of @mantine/* packages do you have in package.json? (Note that all @mantine/* packages must have the same version in order to work correctly)
7.1.5
If possible, please include a link to a codesandbox with a minimal reproduction
No response
Do you know how to fix the issue
No
Do you want to send a pull request with a fix?
No
Possible fix
No response
The text was updated successfully, but these errors were encountered: