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
p.s. .mask is from /
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
p.s. .mask is from http://igorescobar.github.io/jQuery-Mask-Plugin/
Share Improve this question asked Jun 5, 2015 at 16:21 Eugene MatveyevEugene Matveyev 1811 gold badge2 silver badges15 bronze badges 4- FYI not all PANs are 16 digits – Alex K. Commented Jun 5, 2015 at 16:23
- @AlexK. It's OK. That input is just for learning purposes. – Eugene Matveyev Commented Jun 5, 2015 at 16:30
-
1
I cannot speak to why
findDOMNode
is ing back null, but you should be able to just useevent.target
in place of that ref. – Zane M. Commented Jun 5, 2015 at 19:46 - Very good question with few answers around the Internet. – Dherik Commented Dec 18, 2015 at 13:48
3 Answers
Reset to default 3The mask function must be applied to a jquery object, not a plain dom element, and you also need to put this line in ponentDidMount.
ponentDidMount: 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 ponent (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 preputing values based on state — it's easier to ensure that your UI is consistent if you do all putation 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 ponent 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