DEV Community

Cover image for Using React Hook Form with react-native - Part II (pre-filled values & conditional fields)
Sankhadeep Roy
Sankhadeep Roy

Posted on

Using React Hook Form with react-native - Part II (pre-filled values & conditional fields)

This article is a continuation of Part I, where we added RHF to our react-native app. Please make sure you've read the first part for some context.

We'll now see how to pre-fill our fields with data fetched from a server.

Let us make a request to get the email and name of a dummy user from JSONPlaceholder. We add this block of code before the return() statement inside our component (we might need to import useEffect from react if it's not already imported).

useEffect(() => {
  fetchUser();
}, []);

const fetchUser = async () => {
  try {
    const response = await fetch(
      'https://jsonplaceholder.typicode.com/users/1'
    );
    const { name, email } = await response.json();
  } catch (error) {}
};
Enter fullscreen mode Exit fullscreen mode

Now that we have the email and name values, we need to attach them to our form. To do so, we'll use the setValue function from RHF.

// add setValue to the list of destructured functions
const { handleSubmit, control, errors, setValue } = useForm();

// inside fetchUser function
const { name, email } = await response.json();
setValue('name', name);
setValue('email', email);

Enter fullscreen mode Exit fullscreen mode

Now when we run our app, we'll notice that the name and email fields are filled with some values.

Simulator Screen Shot - iPhone 11 - 2020-10-03 at 14.39.38

We can edit these values and when we click on submit, all the validation rules should work as expected.

Now, let us look at how we can add conditional fields to our form using RHF. In our current example, we are using useState to control the toggling of the two extra fields.

form

We'll now connect our switch to our form. To do so, we'll
wrap our <Switch /> component inside Controller from RHF.

<Controller
    defaultValue={false}
    name="isBillingDifferent"
    control={control}
    render={({ onChange, value }) => (
      <Switch
        trackColor={{ false: color.gray200, true: color.green600 }}
        thumbColor={color.gray100}
        ios_backgroundColor={color.gray800}
        onValueChange={onChange}
        value={value}
      />
    )}
  />
Enter fullscreen mode Exit fullscreen mode

Now we need to show/hide the additional fields based on the value of isBillingDifferent. To do so, we'll use the watch function from RHF. It watches the specified inputs and returns their value.

// add watch to the list of destructured functions from useForm
const { ...others,  watch } = useForm();

// watch isBillingDifferent as it changes
const isBillingDifferent = watch('isBillingDifferent');

Enter fullscreen mode Exit fullscreen mode

Make sure we also delete the isBillingDifferent state that we had in our code.

// delete the following line
const [isBillingDifferent, setIsBillingDifferent] = useState(false);
Enter fullscreen mode Exit fullscreen mode

There we have it! Now the additional fields will listen to the isBillingDifferent value to determine whether they need to render.
The only thing that's left for us now is to wire up the additional fields to RHF.

<Controller
   defaultValue=""
   name="billingName"
   control={control}
   rules={{ required: { value: true, message: 'Billing name is required' } }}
   render={({ onChange, value }) => (
     <Input
       error={errors.billingName}
       errorText={errors?.billingName?.message}
       onChangeText={(text) => onChange(text)}
       value={value}
       placeholder="Billing Name"
     />
   )}
 />
<Controller
   defaultValue=""
   name="billingEmail"
   control={control}
   rules={{ required: { value: true, message: 'Billing email is required' }, pattern: { value: EMAIL_REGEX, message: 'Not a valid email' }
            }}
   render={({ onChange, value }) => (
     <Input
       error={errors.billingEmail}
       errorText={errors?.billingEmail?.message}
       onChangeText={(text) => onChange(text)}
       value={value}
       placeholder="Billing email"
     />
   )}
  />
Enter fullscreen mode Exit fullscreen mode

Now we have a fully functional form with validation, pre-filled data and conditional fields!
This example is however only scratching the surface of what RHF can do. I have always struggled with forms and RHF is by far the simplest implementation I've seen so far! Let me know what your preferred solution is for forms in React.

Thanks for reading and do give it a ❤️ if you found it useful!
Happy coding!

Top comments (4)

Collapse
 
matthewdshepherd profile image
matthewdshepherd

Hi there! I am building a similar form with the exception of keeping the Submit button disabled until the required fields meet the criteria I have set for them. I have been using isValid from formState. It all works until I try and reset the form, all of which resets except, isValid showing an enabled submit button Do you have any thoughts on that?

Collapse
 
mauro_codes profile image
Mauro Garcia

Thanks for these posts! I would like to ask you about the last piece of code. I didn't see any reference to the isBillingDifferent prop for the conditional rendering. Am I missing something? Thanks again!

Collapse
 
sankhadeeproy007 profile image
Sankhadeep Roy

Hi, the code where we do the conditional rendering is already a part of App.js. I've covered that in the first part.

Collapse
 
amberkhan1028 profile image
amberkhan1028

I'm new to React Native and this has been very helpful! Thank you