User input validation through React composition and custom hooks.
Tags: react
Published: 2020-10-02 13:05:46

---
title: User input validation through React composition and custom hooks.
published: true
tags: react
---

Let's say you have a relatively simple component. It renders HTML input and handles user submission.

```tsx

type SimpleInputProps = {
  handleChange: Function
}

const handleChange = (value: string): void {
  pushToBackend(changeValue)
}

const SimpleInput = (props: SimpleInputProps): JSX.Element => {
  const { handleChange } = props

  return (
    <input type="text" onChange={handleChange} />
  )
}

```

You want to validate user input. Naturally, you don't want to hard-code the validation logic inside the component. You want to encapsulate it and use it through React composition. Eventually you need to get something like this:

```tsx
const handleChange = ...

const SimpleInput = ...


<ValidationWrapper validations={validationList}>
  <SimpleInput handleChange={handleChange} />
</ValidationWrapper>

```

*I must say, I don't want to use libraries for forms, because they are too heavy for my tasks right now.*

So, we need to implement the `ValidationWrapper` component that encapsulates the validation logic.

As you can see, we want to pass validation handlers as `ValidationWrapper` properties.
The wrapper should take these handlers and decide to execute our `handleChange` function or throw error messages.

So how can we achieve this? Something like that:

```tsx
type ValidationWrapperProps = {
  children: JSX.Element
  validations: Function[]
}

const ValidationWrapper = (props: ValidationWrapperProps): JSX.Element => {
  const { validations, children } = props
  // component must have a handler in props
  const originalHandler = children.props.handleChange

  const { errorMessages, patchedHandler } = useValidation(
    originalHandler, validations,
  )

  return (
    <>
      <children.type {...children.props} handleChange={patchedHandler} />
      {errorsMessages}
    </>
  )
}

```

What's going on here? We just put our input component in a validation wrapper and patch its handler with the `useValidation` hook. Yes, all magic lives on the hook. But it is already clear that this approach looks pretty compact. Let's take a look at the implementation of `useValidation`.

Actually, it can be anything. The main idea is to put the validation logic in one place.
I'll show the simplest example:

```tsx
type ValidationHookProps = {
  callback: Function
  validations: Function[]
}

type ErrorMessages = string[]

const useValidation = (props: ValidationHookProps): ErrorMessages => {
  const { callback, validations } = props
  const [errorMessages, setErrorMessages] = React.useState<ErrorMessages>([])

  const patchedHandler = (changeValue: any): void => {
    const errors = validations.map((validate: Function) => validate(changeValue))

    if (!errors.length) return callback(changeValue)

    setErrorMessages(errors)
  }

  return { errorMessages, patchedHandler }
}

```

It's also pretty simple here. The hook creates a state to store error messages
that we grab from the validation function.

We also create a `handleAction` function. It calls validation handlers and receives messages from them. If we have errors, it won't call the original handler.

The `useValidation` hook returns a patched handler for validating user input and a list of error messages that you can use to display the error to your users.

Thus, we have achieved posibility to check user input through react components composition and custom hooks.