YotKay
YotKay

Reputation: 1207

React problem with react-hook-form and Material-UI

I am trying to construct a form with a dynamic field (and a switch to show/hide it). I want to use both react-hook-forms (for its great features: (1) automatically populate the data structure in the way I want, without me having to do it manually, and (2) the feature of 'watching' input (i.e. reacting to user actions immediately and reflecting this in a variable). I also want to use material-ui, because I need my app to look really modern. According to documentation of react-hook-forms it supports UI libraries, and material-ui is one of them.

But I have a problem. For some kind of inputs, like material-ui's TextField, everything works fine. I can use 'watch' for it, it works perfectly. But for some others inputs, like Switch or Checkbox, the watch feature doesn't work well.

For example, in this particular test example, the page reacts well when I type something in the TextField (I can see it also in console), the watch displays correct value. But when I click the Switch element, something strange happens. The first time it works OK, my dynamic field appears, var isDog is set to true which is OK. But for the second time even though isDog value is false the code (the conditional rendered field) behave as if it was still true, and the result is that the dynamic field is rendered forever. Like it was cached somewhere or I don't know. What is going on here?

I tried using different 'value' in the code, e.g. "true", or place the value attribute in RFHInput itself, rather than in Switch (controlled by FormControlLabel), but nothing helps.

Anyone had the same problem? What is wrong here? Is this a bug?

import React from "react";
import { useForm } from 'react-hook-form'
import Switch from '@material-ui/core/Switch';
import TextField from '@material-ui/core/TextField';
import { RHFInput } from 'react-hook-form-input';
import Button from '@material-ui/core/Button';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import ReactDOM from 'react-dom';

export default function App() {
   const { register, handleSubmit, watch, setValue } = useForm()

   const onSubmit = data => {
      console.log(data)
   }
   var isDog = watch("dog", false)
   var nameOfPet = watch("petname", "noname")
   console.log("isDog = " + isDog)  
   console.log("nameOfPet = " + nameOfPet)  
   return (
      <form onSubmit={handleSubmit(onSubmit)}>

         <RHFInput as={<TextField variant="outlined" margin="normal" required fullWidth label="name of your pet" autoFocus />}
               register={register} setValue={setValue} name="petname" />
         <RHFInput as={<FormControlLabel control={<Switch value={!isDog} />} label="dog" />}
            register={register} setValue={setValue} name="dog" />             

         <h2>Name of your pet is "{nameOfPet}" </h2>
         {isDog && (<RHFInput as={<TextField variant="outlined" margin="normal" required fullWidth label="how many legs does your dog have?" autoFocus />}
               register={register} setValue={setValue} name="petname" />)}
         {/* {!isDog && (<h1>It is not a dog!</h1>)} */}
         <Button type="submit" fullWidth variant="contained" color="primary" > Submit </Button>

       </form>
   );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Here is the example in codesandbox Link to codesandbox

Upvotes: 2

Views: 10367

Answers (3)

Rajendran Nadar
Rajendran Nadar

Reputation: 5438

The ideal solution is to spread the register from the react hook forms

<FormControlLabel
  control={<Switch />}
  {...register('dog')}
  label="dog" 
/>

You will get the register from the useForm from the react-hook-form package

Upvotes: 0

SaimumIslam27
SaimumIslam27

Reputation: 1188

<FormControlLabel
  control={<Switch onChange={register('active').onChange}
                inputRef={register('active').ref}
 />}
  label="dog" 
/>

Upvotes: 0

awran5
awran5

Reputation: 4536

It seems that RHFInput have some bugs when combined with Material-UI Switch.

Try to remove it and change the register ref to inputRef

<FormControlLabel
  control={<Switch inputRef={register} name="dog" />}
  label="dog" 
/>

Also, please note you have to change the second input name in order to get its value.

Here is your codesandBox example.

Upvotes: 4

Related Questions