简体   繁体   中英

Mask card number input in React

I'm learning React and want to make an input with two constraints:

  • 16 numbers,
  • put a space after every fourth.
import React, { Component } from 'react';

export default class CardNumberInput extends Component {
  constructor() {
    super();
    this.state = { value: '' };
  }

  handleChange(event) {
    React.findDOMNode(this.refs.cardInput).mask("0000 0000 0000 0000");
    this.setState({ value: event.target.value });
  }

  render() {
    let value = this.state.value;

    return (
      <div>
        <label htmlFor="cardInput">Card Number: </label>
        <input ref="cardInput" id="cardInput" onChange={this.handleChange} type="number" value={value} />
      </div>
    );
  }
}

I don't know whether I'm doing it right (use refs), because console.log(React.findDOMNode(this.refs.cardInput)) returns null o_O

ps .mask is from http://igorescobar.github.io/jQuery-Mask-Plugin/

The mask function must be applied to a jquery object, not a plain dom element, and you also need to put this line in componentDidMount.

componentDidMount: function () {
    var $input_elem = $(React.findDOMNode(this.refs.cardInput));
    // now you have a jquery object
    $input_elem.mask("0000 0000 0000 0000", callback_options);
}

However, the callback options for this plugin still need to be integrated with the react lifecycle methods. First try making it an uncontrolled component (use defaultValue instead of value) and check that it works.

You are rendering this.state.value every time you make a change, which is overwriting the mask.

The mask is being overwritten by the render.

You need to move the mask() to render so that it masks the value before it writes to the dom.

Computed data: Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within render(). For example, if you have an array of list items in state and you want to render the count as a string, simply render this.state.listItems.length + ' list items' in your render() method rather than storing it on state. https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html

I created a package that exposes an input component that displays a masked value according to the mask it receives.

The mask will change keeping the cursor at the correct position (even if you change part of the value in the middle of the input, paste some characters, or delete a part of it, and even if the mask changes).

You can see a Demo with examples at:

https://lucasbasquerotto.github.io/react-masked-input

You can see in the 1st example a mask similar to a credit card, and the value your receive doesn't have mask (only the display value). Just change the mask to 9999 9999 9999 9999 and it will work for your case.

To install the package: npm i react-hook-mask

You can use dynamic masks if later you want to change the credit card mask based on the value (because some credit cards have different masks).

I created a demo with an example according to what you asked (it uses the mask 9999 9999 9999 9999 ):

https://codesandbox.io/s/credit-card-mask-8f3w8?file=/src/index.js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM