Input Mask in React without libraries
Tags: react, javascript, frontend
Published: 2021-05-29 03:30:30

## How to create a simple input mask only with React:

There are many libraries to do this, but it is always good to know how to do things that work in any type of web development. In this case we will create an entry for credit cards.

### Step 1:

In a functional component we import 

```
import React, { useState, useEffect, useRef } from 'react';
```

Now, we can created the component, in this case, the name is `InputMask`

```
const InputMask = () => {
  
}

export default InputMask;

```

### Step 2:

We create first a new state, called `card`, and `setCard` is the function to modify that `state`, later we create a `const` called `inputCard` for the `useRef` hook.

```
import React, { useState, useEffect, useRef } from "react";

const InputMask = () => {
  const [card, setCard] = useState();
  const inputCard = useRef()
}

export default InputMask;
```

Now, we return an input with a ref property binding the InputCard const

```
import React, { useState, useEffect, useRef } from 'react';

const InputMask = () => {
  const [card, setCard] = useState();
  const inputCard = useRef();

  return (
    <>
      <input type="text" ref={inputCard} />
    </>
  );
};

export default InputMask;
```

If you do not know the hook `useRef` I share the official React documentation for `useRef` [in this link](https://reactjs.org/docs/hooks-reference.html#useref) 

### Step 3:

Now, we can target the events of the input, useRef works like a eventListener in JavaScript! For that, we create a function called `handleChange` and pass this function to the input in a `onChange` event

```
import React, { useState, useEffect, useRef } from 'react';

const InputMask = () => {
  const [card, setCard] = useState();
  const inputCard = useRef();

  const handleChange = () => {
    
  };

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

export default InputMask;
```

### Step 4:

In `handleChange` we use [regex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) (Regular expressions) in a first step we use `replace` to replace all the expressions that not numbers with a blank space, later we use `match` for grouping the digits of the  credit card in four groups of four digits each one

```
import React, { useState, useEffect, useRef } from 'react';

const InputMask = () => {
  const [card, setCard] = useState();
  const inputCard = useRef();

  const handleChange = () => {
    const cardValue = inputCard.current.value
      .replace(/\D/g, '')
      .match(/(\d{1,4})(\d{0,4})(\d{0,4})(\d{0,4})/);
    inputCard.current.value = !cardValue[2]
      ? cardValue[1]
      : `${cardValue[1]}-${cardValue[2]}
      ${(`${cardValue[3] ? `-${cardValue[3]}` : ''}`)}
      ${(`${cardValue[4] ? `-${cardValue[4]}` : ''}`)}`;
  };

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

export default InputMask;
```

Look at this, after `match`, we use a` ternary operator` to set the `value` for` inputCard` in a first step, we set the condition of the second group to false, because group one will always exist, in a second step , we write many conditions, at the beginning group one, then the second group will continue, then if group three exists it will be after a `-`, the same is for group four...

### Step 5:

Finally, we use the `useEffect` hook to manage the component lifecycle, inside useEffect, we set the callback for handleChange, and we specify the render when the `card state` changes, for this, we use `setCard` to save the input value on `card state`

```
import React, { useState, useEffect, useRef } from 'react';

const InputMask = () => {
  const [card, setCard] = useState();
  const inputCard = useRef();

  const handleChange = () => {
    const cardValue = inputCard.current.value
      .replace(/\D/g, '')
      .match(/(\d{0,4})(\d{0,4})(\d{0,4})(\d{0,4})/);
    inputCard.current.value = !cardValue[2]
      ? cardValue[1]
      : `${cardValue[1]}-${cardValue[2]}${`${
          cardValue[3] ? `-${cardValue[3]}` : ''
        }`}${`${cardValue[4] ? `-${cardValue[4]}` : ''}`}`;
    const numbers = inputCard.current.value.replace(/(\D)/g, '');
    setCard(numbers);
  };

  useEffect(() => {
    handleChange();
  }, [card]);

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

export default InputMask;
```

This code works on phone inputs! in that case we must use `(xxx)` in the beginning of the input.

[Demo](https://maskinput.stackblitz.io/)

Hope you like this post!