Skip to content

Forthtilliath/react-use-form-fields-ref

Repository files navigation

react-use-form-fields-ref

en fr

Introduction

npm version npm download github repo size licence

The @forthtilliath/react-use-form-fields-ref package is a library that provides a React hook called useFormFieldsRef. This hook allows you to manage form field references in a React component. It returns an array containing two elements: an object that contains the references for each field, and an object that contains functions to interact with these references.

The useFormFieldsRef hook is useful for simplifying the management of form fields in a React component. It makes it easy to define references for each field and to interact with these references in a consistent way. The @forthtilliath/react-use-form-fields-ref package is easy to use and can be installed via NPM, Yarn or PNPM.

Install

Install it from npm and include it in your React build process

npm install --save @forthtilliath/react-use-form-fields-ref

or from yarn:

yarn add --dev @forthtilliath/react-use-form-fields-ref

or from pnpm:

pnpm install --save @forthtilliath/react-use-form-fields-ref

Usage

Here's a sample form showing how to use the useFormFieldsRef hook to handle references for input fields, radio buttons, and a drop-down list:

JSX

import { useFormFieldsRef } from "@forthtilliath/react-use-form-fields-ref";

export function MyForm() {
  const [
    fieldsRef,
    { setRef, getRef, getField, getAllRef, getFormData, isFieldNotNull },
  ] = useFormFieldsRef(["username", "password", "gender", "message", "age"]);

  const handleSubmit = () => {
    const usernameField = getField("username");
    if (isFieldNotNull(usernameField)) {
      console.log(usernameField.value);
    }
    console.log(getRef("age"));
    console.log(getAllRef());
    console.log(Object.fromEntries(getFormData()));
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Examples with inputs fields */}
      <input type="text" ref={setRef("username")} placeholder="Username" />
      <input type="password" ref={setRef("password")} placeholder="Password" />

      {/* Examples with radio buttons */}
      <label>
        <span>Minor:</span>
        <input type="radio" name="age" ref={setRef("age")} value="minor" />
      </label>
      <label>
        <span>Major:</span>
        <input type="radio" name="age" ref={setRef("age")} value="major" />
      </label>

      {/* Examples with a drop-down list */}
      <select ref={setRef("gender")} defaultValue={"default"}>
        <option value="default" disabled>
          Gender
        </option>
        <option value="male">Male</option>
        <option value="female">Female</option>
        <option value="other">Other</option>
      </select>

      <textarea ref={setRef("message")} placeholder="Message" />
      <button type="submit">Submit</button>
    </form>
  );
}

TSX

import { useFormFieldsRef } from "@forthtilliath/react-use-form-fields-ref";

export function MyForm() {
  const [
    fieldsRef,
    { setRef, getRef, getField, getAllRef, getFormData, isFieldNotNull },
  ] = useFormFieldsRef(["username", "password", "gender", "message", "age"]);

  const handleSubmit: React.FormEventHandler<HTMLFormElement> = () => {
    const usernameField = getField("username");
    if (isFieldNotNull(usernameField)) {
      console.log(usernameField.value);
    }
    console.log(getRef("age"));
    console.log(getAllRef());
    console.log(Object.fromEntries(getFormData()));
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Examples with inputs fields */}
      <input type="text" ref={setRef("username")} placeholder="Username" />
      <input type="password" ref={setRef("password")} placeholder="Password" />

      {/* Examples with radio buttons */}
      <label>
        <span>Minor:</span>
        <input type="radio" name="age" ref={setRef("age")} value="minor" />
      </label>
      <label>
        <span>Major:</span>
        <input type="radio" name="age" ref={setRef("age")} value="major" />
      </label>

      {/* Examples with a drop-down list */}
      <select ref={setRef("gender")} defaultValue={"default"}>
        <option value="default" disabled>
          Gender
        </option>
        <option value="male">Male</option>
        <option value="female">Female</option>
        <option value="other">Other</option>
      </select>

      <textarea ref={setRef("message")} placeholder="Message" />
      <button type="submit">Submit</button>
    </form>
  );
}

The code uses the useFormFieldsRef hook to create a reference for each input field in the form. This function returns an array containing two elements: an object of references for each input field, and an object containing functions to interact with the references.

Once the references are created, the code defines the input fields of the form using the JSX elements <input>, <select>, and <textarea>. For each input field, it uses the setRef function provided by useFormFieldsRef to create a reference.

When the user submits the form by clicking on the "Submit" button, the code calls the handleSubmit function, which uses the functions provided by useFormFieldsRef to access the current values of the input fields, and logs them to the console.

useFormFieldsRef return

The hook returns an array containing two elements:

  • The first element is an initialized useRef object with an object containing null values for each input.
  • The second element is an object containing functions to interact with the useRef object.

First key : useRef object

The first element is the reference which contains all fields. You can access them in the following way :

JSX / TSX

const [myFormRef, actions] = useFormFieldsRef(myFields);

const checkInput = () => {
  // Focus the input if it's empty
  // myInput has the type HTMLFieldElement | null
  // HTMLFieldElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
  const myInput = refs.current.username;
  if (myInput && myInput.value === "") {
    myInput.focus();
  }
};

Here, we can see that refs.current.username corresponds to the reference for the username field. This reference can be used to access the current value of the input field.

Second key : actions

The second item is an object that contains all the actions. Here's a list of these functions with a brief description of what they do:

  • getFieldsRef: returns an object that contains the references for each field.
  • setRef: returns a function that takes an HTMLInputElement, HTMLSelectElement, or HTMLTextAreaElement element as an argument and sets the reference for the corresponding field name.
  • getRef: returns the reference for the corresponding field name.
  • getField: returns an object containing the reference and value for the corresponding field name.
  • getAllRefs: returns an object containing all the references for each field.
  • getFormData: returns an array containing key-value pairs for each field.
  • isFieldNotNull: returns true if the field is not null, else false.

setRef

setRef returns a callback used to update the reference bound to the given key.

JSX / TSX

<input type="text" ref={setRef("username")} placeholder="Username" />

In this example, setRef("username") is used to create a reference for the input field.

getRef

getRef returns the value contained in the fieldsRef reference to the given key. An input radio will return an empty string.

JSX / TSX

const [, { getRef }] = useFormFieldsRef(["username", "password"]);

const handleSubmit = () => {
  console.log(getRef("username"));
};

The code creates references for the "username" and "password" input fields using useFormFieldsRef, and uses getRef to obtain the value of the "username" input field when handleSubmit is called and display it.

getField

getField returns the element contained in the fieldsRef reference to the given key. An input radio will return an array of input which contains HTMLInputElement from the given key.

JSX

const [, { getField }] = useFormFieldsRef(["username", "password"]);

const checkInput = () => {
  const myUsernameInput = getField("username");
  if (myUsernameInput.value === "") {
    myUsernameInput.focus();
  }
};

TSX

const [, { getField }] = useFormFieldsRef(["username", "password"]);

const checkInput = () => {
  const myUsernameInput = getField<HTMLInputElement>("username");
  if (myUsernameInput.value === "") {
    myUsernameInput.focus();
  }
};

The code creates a reference for the "username" input field using useFormFieldsRef, and uses getField to obtain the value of the "username" input field when checkInput is called. If the value of the input field is an empty string, checkInput sets the focus on the "username" input field.

getAllRef

getAllRef returns an object containing values from a list of input references.

JSX / TSX

const [, { getAllRef }] = useFormFieldsRef(["username", "password"]);

const handleSubmit = () => {
  console.log(getAllRef());
};

The code creates references for the "username" and "password" input fields and uses getAllRef to obtain the values of both input fields when handleSubmit is called and logs them to the console.

getFormData

getFormData gets form data from input fields and returns it as a FormData object.

JSX / TSX

const [, { getFormData }] = useFormFieldsRef(["username", "password"]);

const handleSubmit = () => {
  console.log(Object.fromEntries(getFormData()));
};

The code creates references for the "username" and "password" input fields and defines a function getFormData that returns a FormData object containing the values of the input fields. When handleSubmit is called, the code logs an object containing the values of the input fields to the console.

isFieldNotNull

isFieldNotNull is a function that checks if a given HTMLFieldElement is not null.

JSX

const focusIfEmpty = (key) => {
  const field = getField(key);
  if (isFieldNotNull(field)) {
    if (field.value === "") field.focus();
  } else {
    throw new Error(`The field with ${key} key is null`);
  }
};

TSX

type InputKey = (typeof inputsName)[number];

const focusIfEmpty = (key: InputKey) => {
  const field = getField(key);
  if (isFieldNotNull(field)) {
    if (field.value === "") field.focus();
  } else {
    throw new Error(`The field with ${key} key is null`);
  }
};

The code defines a function focusIfEmpty that sets the focus on an input field if it is empty, and throws an error if the field is null.

Utility types

UseFormFieldsRefActions

The UseFormFieldsRefActions type helps to get the return type of the second parameter of the hook. This can be useful when you pass setRef to a child.

TSX

// In your form component
export const connexionInputs = ["username", "password"] as const;

// In your child component
import { UseFormFieldsRefActions } from "@forthtilliath/react-use-form-fields-ref";

// Action contains all actions type
type InputKey = (typeof connexionInputs)[number];
type Action = UseFormFieldsRefActions<InputKey>;

type Props = {
  // Note the setRef to get only the type of the methode setRef
  setRef: Action["setRef"];
};

Example Usage

Check out this StackBlitz example (JS version) to see how these functions can be used in a React form.

In the example, you can see how the useFormFieldsRef hook is used to manage the form fields and how the other functions can be used to access or manipulate the form data. Feel free to fork the example and experiment with it yourself!

Let me know if you have any questions or feedback about the example.

Releases

No releases published

Packages

No packages published