loading...
Cover image for Using React Hook Form v6+ with Ionic React Components - Update
Ionic

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

aaronksaunders profile image Aaron K Saunders ・1 min read

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>
  );
};

Updated Example Source Code From Stackblitz

Original Video Showing the Use of React Hook Form

Posted on Jul 17 by:

Discussion

markdown guide
 

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?

 

Thanks for this quick update