DEV Community

Cover image for Using React Hook Form v6+ with Ionic React Components - Update
Aaron K Saunders for Ionic

Posted on • Edited on

14 6

Using React Hook Form v6+ with Ionic React Components - Update

🔆Click Here for Ionic Framework ReactJS and VueJS Tips/Tutorials?🔆

This is a quick post showing quickly how to make latest version of React Hook Form work with Ionic Framework ReactJS Components.

The previous post example will only work on older versions of the form library.

This is based on the Controller API discussed here in the documentation - https://react-hook-form.com/api#Controller

const App: React.FunctionComponent = () => {
  const { handleSubmit, control } = useForm();

  /**
   *
   * @param data
   */
  const onSubmit = (data: any) => {
    debugger;
    alert(JSON.stringify(data, null, 2));
  };

  return (
    <IonApp>
      <IonPage>
        <IonHeader>
          <IonToolbar>
            <IonButtons slot="start">
              <IonBackButton />
            </IonButtons>
            <IonTitle>Detail</IonTitle>
          </IonToolbar>
        </IonHeader>
        <IonContent>
          <p>Details</p>
          <form onSubmit={handleSubmit(data => console.log(data))}>
            <IonItem>
              <IonLabel>Gender</IonLabel>
              <Controller
                render={({ onChange, onBlur, value }) => (
                  <IonSelect placeholder="Select One" onIonChange={onChange}>
                    <IonSelectOption value="FEMALE">Female</IonSelectOption>
                    <IonSelectOption value="MALE">Male</IonSelectOption>
                  </IonSelect>
                )}
                control={control}
                name="gender"
                rules={{ required: true }}
              />
            </IonItem>
            <IonItem>
              <IonLabel>Email</IonLabel>
              <Controller
                render={({ onChange, onBlur, value }) => (<IonInput onIonChange={onChange}/>)}
                control={control}
                name="email"
                rules={{
                  required: true,
                  pattern: {
                    value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
                    message: "invalid email address"
                  }
                }}
              />
            </IonItem>
            <IonItem>
              <Controller
                render={({ onChange, onBlur, value }) => (
                  <IonRange
                    min={-200}
                    max={200}
                    color="secondary"
                    onIonChange={onChange}
                  >
                    <IonLabel slot="start">-200</IonLabel>
                    <IonLabel slot="end">200</IonLabel>
                  </IonRange>
                )}
                control={control}
                name="rangeInfo"
                rules={{ required: true }}
              />
            </IonItem>
            <IonButton type="submit">submit</IonButton>
          </form>
        </IonContent>
      </IonPage>
    </IonApp>
  );
};
Enter fullscreen mode Exit fullscreen mode

Updated Example Source Code From Stackblitz

Original Video Showing the Use of React Hook Form

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (15)

Collapse
 
aaronksaunders profile image
Aaron K Saunders • • Edited

Saw this issue on Stackoverflow, stackoverflow.com/questions/630772...

here is a workaround

You can just add the interface...

export interface CheckboxChangeEventDetail {
  value: any;
  checked: boolean;
}
Enter fullscreen mode Exit fullscreen mode

and then set the code

<IonItem>
  <Controller
    render={({ onChange, onBlur }) => (
      <IonCheckbox
        onIonChange={(e: CustomEvent<CheckboxChangeEventDetail>) => {
          onChange(e?.detail.checked);
          console.log(e);
        }}
        onIonBlur={onBlur}
      />
    )}
    control={control}
    defaultValue={false}
    name="saveInfo"
    rules={{
      required: false,
    }}
  />
</IonItem>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
curiouswebs profile image
curious-webs •

Tried using interface for email field But still getting "Property 'onChange' does not exist on type"
in here
render={({ onChange, onBlur, value }) => (

Collapse
 
wendyperalta profile image
Wendy •

Thank you for updating this. How would you go about testing this component? I have a simple Ionic Text Input component wrapped in a Controller just like the example above.

<Controller
      control={control}
      name="emailInput"
      rules={{ required: true }}
      render={({ value, onChange, onBlur }) => (
        <IonInput
          type="text"
          value={value}
          data-testid="input-email"
          onIonChange={onChange}
          onBlur={onBlur}
        />
      )}
    />

I've tried to use the example from this article:

import { ionFireEvent as fireIonEvent } from "@ionic/react-test-utils";
const emailInput = await findByTestId("input-email");
fireIonEvent.ionChange(emailInput, "test@email.com");

I've also tried this (since ion input components have a detail property that specifies the value of the input:

import { fireEvent } from "@testing-library/react";
fireEvent.change(emailInput, { target: { detail: { value: {"test@email.com" }}});

None of these methods get me what I need which is the value for these inputs being updated in the test. Any ideas?

Collapse
 
patelrikin profile image
Rikin Patel •

You can probably do debug() from testing library after each fired event and see if the thing changed at all to investigate

Collapse
 
wendyperalta profile image
Wendy •

I did do that, but it didn't change.

Thread Thread
 
aaronksaunders profile image
Aaron K Saunders •

put the id on the Controller and fire a onChange event don't use the ionic events

Thread Thread
 
wendyperalta profile image
Wendy •

When I moved the data-testid='input-email' to the Controller component wrapper, now I get an error in the test:
TestingLibraryElementError: Unable to find an element by: [data-testid="input-email"]
I'm assuming because it is a custom component.

Thread Thread
 
aaronksaunders profile image
Aaron K Saunders •

can you put a simple project together on stackblitz?

Thread Thread
 
uxtx_tim profile image
Tim Proffitt •

Im curious what came of this - having the same issues :(

Collapse
 
gvilomar profile image
gvilomar •

Hi @aaronksaunders , I'm having an issue with Ionic 7, react-hook-form, and modals. If I submit the page and it finds errors, the error messages do not disappear even though I fix the error. Also, it can continue. I've watched several of your videos and read through many of your post but I cannot see what is wrong. See my code below. Let me know if you have any other suggestions I can try. Thanks in advance!

stackblitz code

Collapse
 
gvilomar profile image
gvilomar •

Sorry @aaronksaunders, the link above was for the app and not the code. Here's the code link:

code

Collapse
 
clementvp profile image
Van Peuter Clément •

Hello, How do you reset the form ? Or how do you set values to the form (with a proper render of the form ?)

Collapse
 
aaronksaunders profile image
Aaron K Saunders •

you reset the form using the reset method from the hook... you set the form using the default values, it is funny that you asked because i was working on a blog post about that!!

Collapse
 
aaronksaunders profile image
Aaron K Saunders •
Collapse
 
patelrikin profile image
Rikin Patel •

Thanks for this quick update

The best way to debug slow web pages cover image

The best way to debug slow web pages

Tools like Page Speed Insights and Google Lighthouse are great for providing advice for front end performance issues. But what these tools can’t do, is evaluate performance across your entire stack of distributed services and applications.

Watch video

đź‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay