bietkul/react-reactive-form

Not updating with react hooks

sayax opened this issue · 2 comments

sayax commented

Describe the bug
A clear and concise description of what the bug is.
Field Group state not updating with react useState hook

To Reproduce
Steps to reproduce the behavior:

  1. Create reactive form
  2. create const [loading, setLoading] = useState(false)
  3. create button
    <Button disabled={!form.valid || loading} className="primary" onClick={submit} />
  4. change state on click
    const submit = () => {
    setLoading(true);
    }

Expected behavior
A clear and concise description of what you expected to happen.
button disabled has loading = true state
Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

sayax commented

1.5) create form template

    <FieldGroup
      control={form}
      render={({ get, invalid }) => (
          <>
          <FieldControl
            name="username"
            render={({ handler, touched, hasError, meta }) => (
            <StyledFormField
              error={
                (touched && hasError('required') && 'required')
              }
            >
              <Input
                as={MaskedInput}
                mask={['+', '7', ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, ' ', /\d/, /\d/]}
                placeholder=""
                {...handler()}
              />
            </StyledFormField>
            )}
          />
          <Button disabled={!form.valid || loading} className="primary" onClick={submit} />
          </>
      )}
    />

By default, Field components only get re-render only when there is a change in the control's state.
It's recommended to not use the state under the Field component for better performance.
I can see that you're using a state variable named loading, it's better to put the Button component outside of the form, for example:

import { Field, ... } from 'react-reactive-form';
...
<>
  <FieldGroup
      control={form}
      render={({ get, invalid }) => (
          <>
          <FieldControl
            name="username"
            render={({ handler, touched, hasError, meta }) => (
            <StyledFormField
              error={
                (touched && hasError('required') && 'required')
              }
            >
              <Input
                as={MaskedInput}
                mask={['+', '7', ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, /\d/, ' ', /\d/, /\d/, ' ', /\d/, /\d/]}
                placeholder=""
                {...handler()}
              />
            </StyledFormField>
            )}
          />
          </>
      )}
    />
  <Field
    strict={false}
    control={form}
    render={({ invalid }) => <Button disabled={invalid || loading} className="primary" onClick={submit} />}
  />  
</>

If you still want to bypass it, please use strict prop as false in FieldGroup and FieldControl to avoid this default behavior, check here.