DEV Community

Rick1196
Rick1196

Posted on

How to avoid invalid inputs in react

Avoid invalid inputs in react

So you want to avoid your user typing invalid characters in, for example, a numeric input? You only need a custom hook and a regex or a custom function.

Important note!!!: This validation will not replace any validation library and will not work on mobile devices.

your can check the a code and a live demo at code sandbox

Lets build the custom hook

Let's add a custom hook to add an event listener to a specific element and trigger a function when that event happens.

import { useEffect } from "react";

type EventListenerParams = {
  action: (event: Event) => void; // waht do we watn to perform with the event
  event: string; // what event do we want to liste
  idElement: string; // the element that we want to bind to the listener
};

/**
 * Add a event listener for a specific event to a specific element
 */
const useEventListener = (params: EventListenerParams): void => {
  useEffect(() => {
    // on init add event listner
    window.document
      .getElementById(params.idElement)
      ?.addEventListener(params.event, params.action);
    // on component unmount, remove the event listener to avoid performance issues
    return () =>
      window.document
        .getElementById(params.event)
        ?.removeEventListener(params.event, params.action);
  });
};

export default useEventListener;

Enter fullscreen mode Exit fullscreen mode

With this custom hook, You just need to pass the parameters for each element or event you want to listen for; don't forget to add the return statement to the custom hook, to remove the event listener at component unmount.

Now lets create a couple of validation functions to test our custom hook

The first one to validate the length of an input value
The second one to validate if the value of an input matches with a regex

/**
 * Check if the current length of the input value is minor to a fixed length
 * @param maxLength of your input
 */
export function lengthValidator(maxLength: number) {
  return function validation(event: Event): void {
    const element = event.target as HTMLInputElement;
    // if the value length is already equals to maxLength
    if (element.value.length >= maxLength) {
      //  cancel the event and their side effects
      event.preventDefault();
    }
  };
}
/**
 * Check if the current value of the input plus the key pressed match with a pattern
 * @param regex to compare the input value
 */
export function matchValidator(regex: RegExp) {
  return function validation(event: Event): void {
    // get the element
    const element = event.target as HTMLInputElement;
    // get the element current value plus the input key value
    const stringToValidate = String(
      element.value + (event as KeyboardEvent).key
    );
    // if input value does not match with the regex
    if (!stringToValidate.match(regex)) {
      // cancel the event and their side effects
      event.preventDefault();
    }
  };
}

Enter fullscreen mode Exit fullscreen mode

Now lets add some input fields to test our creation

import useEventListener from "./use-event-listener";
import { lengthValidator, matchValidator } from "./validations";

export default function App() {
  useEventListener({
    action: lengthValidator(10),
    event: "keypress",
    idElement: "max-length"
  });
  /**
   * Validates that max-length field never be longer than 10
   */
  useEventListener({
    action: lengthValidator(10),
    event: "keypress",
    idElement: "max-length"
  });
  /**
   * Validates that numbers-only always contains numeric characters
   */
  useEventListener({
    action: matchValidator(new RegExp("^[\\d]+$")),
    event: "keypress",
    idElement: "numbers-only"
  });
  return (
    <div className="App">
      <div>
        <label>Input for with max length of 10</label>
        <input
          placeholder="Enter a name with no more of 1- characters"
          type="text"
          id="max-length"
        />
      </div>
      <div>
        <label>Input only for numbers</label>
        <input placeholder="Enter only numbers" type="text" id="numbers-only" />
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

And that's all, now you can use the custom hook in all the components you want, and you can implement your validation functions.

Discussion (0)