React Input Component Validate Zip Code

Today I wanted to share a react snippet for Zip Code validation within an input.

The full example of the code is all the way at the bottom, but first I wanted to share a list of all the things this example gets into.

  • A Reusable React Input Component
  • Input handling (keydown, keyup, and paste events)
  • Numeric keyboard on input focus when using mobile devices
  • Utility function helpers
  • Local storage
    • Initial React application state
    • Updating application state upon local storage being set

Reusable React Component

Below is the boilerplate Input component and how to implement it:

import React, { Component } from "react";

// component
class Input extends Component {
  // default props for input
  static defaultProps = {
    onInput: "",
    onKeyDown: "",
    onKeyUp: "",
    // this is an example of removing the paste
    // functionality entirely across the board
    // onPaste: (e) => { e.preventDefault() },
    onPaste: "",
    max: "",
    min: "",
    inputmode: "",
    pattern: "",
    placeholder: "",
    type: "text"
  };

  render() {
    return (
      <input
        inputMode={this.props.inputmode}
        max={this.props.max}
        min={this.props.min}
        onInput={e => {
          this.props.onInput === "" ? "" : this.props.onInput(e);
        }}
        onKeyDown={e => {
          this.props.onKeyDown === "" ? "" : this.props.onKeyDown(e);
        }}
        onKeyUp={e => {
          this.props.onKeyUp === "" ? "" : this.props.onKeyUp(e);
        }}
        onPaste={e => {
          this.props.onPaste === "" ? "" : this.props.onPaste(e);
        }}
        pattern={this.props.pattern}
        placeholder={this.props.placeholder}
        type={this.props.type}
        defaultValue={this.props.value}
      />
    );
  }
}

export default Input;

Input handling

Next we want to take a look at the input handling functions:

handleZipcodeInputKeyDown = e => {
  // this is called as soon as we get input from the user
  // we don't want to allow them the access to input past 5 digits
  // so we block on keyDown
  // (it never gets to keyUp, which actually updates the state)

  // restrict to 5 digits only
  // but allow backspace and arrow
  var key = e.which ? e.which : e.keyCode;
  if (
    (e.target.value.length >= 5 &&
      key !== 8 &&
      key !== 37 &&
      key !== 38 &&
      key !== 39 &&
      key !== 40) ||
    (key === 18 || key === 189 || key === 229)
  ) {
    e.preventDefault();
  }
};

handleZipcodeInputKeyUp = e => {
  // set state of zipcode
  this.setState({
    zipCode: e.target.value
  });
};

handleZipcodeInputPaste = e => {
  e.preventDefault();
  // get pasted content
  let pasteText = e.clipboardData.getData("text/plain");
  // only allow integers
  pasteText = pasteText.replace(/[^0-9]/g, "");
  // add to current input value (target)
  let newContent = e.target.value + pasteText;
  // only allow 5 digits total
  newContent = newContent.substring(0, 5);
  // set new value of input
  e.target.value = newContent;
  // set new state of zipcode
  this.setState({
    zipCode: newContent
  });
};

Numeric keyboard (mobile devices)

Forcing the numeric keyboard on input focus with these lines:

Notice: inputmode, pattern & type props passed to our component.

// put at the top of our App.js file
import Input from "./input";

// put within our render function
<Input
  inputmode="numeric"
  onKeyDown={e => this.handleZipcodeInputKeyDown(e)}
  onKeyUp={e => this.handleZipcodeInputKeyUp(e)}
  onPaste={e => this.handleZipcodeInputPaste(e)}
  pattern="\d*"
  placeholder="Enter zipcode"
  type="number"
  value={this.state.zipCode}
/>

Including Utility Helpers and Usage

Include the helper utility for local storage and an example of setting it (on zip code submit).

// put at the top of our App.js file
import { localDataGet, localDataSet, localDataDelete } from "./utilities";

// put within our App.js React highlevel component
handleZipcodeSubmit = () => {
  // store the zip code in local storage
  localDataSet("zipCode", this.state.zipCode);
};

Local Storage Load In

Then within our constructor we want to add before the initial state

constructor(props) {
  super(props);

  // local storage call
  const userLocalData = localDataGet();
  // console.log("data from local storage");
  // console.log(userLocalData);

  // initial app state
  this.state = {
    zipCode: userLocalData.zipCode ? userLocalData.zipCode : ""
  };
}

Demo the thing…

Edit React :: Input Validation for Zip Code