29 May 2022 | 2 minute read

Playing with React Hooks

Even though I write a fair bit of React code in my day to day, it tends to be within a system that is currently “frozen” at version 16.5.2… meaning Hooks aren’t an option at the minute.

So when working on a side project, I jumped at the chance to work in some custom hooks where possible!

Some simple validation

So I had a simple form with a few fields, and the need to validate one of them to ensure it only contained alphanumeric characters and hyphens. I then set this isValid value to local state, showing a validation message if something funky has crept in.

(It’s worth saying at this point I could just use Formik here but my forms are so simple I thought I’d stay off npm for now :)

So the first pass using the useState hook looked something like this:

const slugRegex = new RegExp(/^([a-z0-9\-]*)$/);
const [validSlug, setValidSlug] = useState(true);

function validateSlug(updatedSlug) {
  const isSlugValid = slugRegex.test(updatedSlug);
  setValidSlug(isSlugValid);
}

function onChange(e) {
  validateSlug(e.target.value);
}

So far, so contrived :) Although given I have more than one place I needed to use the validation, it felt like an opportunity to “hookify” the code!

Time for the Hook

As per the React advice I started out with a function prefixed with the word “use” and moved the state and the validator function inside:

import { useState } from "react";

const SlugRegEx = new RegExp(/^([a-zA-Z0-9\-]*)$/);

export const useSlugValidation = (initialValue) => {
  const [isValidSlug, setIsValidSlug] = useState(initialValue);
  const validateSlug = (slug) => {
    const isValid = SlugRegEx.test(slug);
    setIsValidSlug(isValid);
  };

  return [isValidSlug, validateSlug];
};

Then using it was pretty straightforward:

const [isValidSlug, validateSlug] = useSlugValidation(true);

function onChange(e) {
  validateSlug(e.target.value);
}

function updateCurrentPost() {
  if (!isValidSlug) {
    console.log("Unable to save post - correct the slug!");
    return;
  }
}

And that’s it! Of course I could add additional validation rules, and can see how I might make the whole thing more generic. But as a simple refactor I’m happy enough :)