I need to build a email verification for which requires a code sent to the user's email address. Very similar to the way Slack handle's email verification in their signup flow:
When you paste, the pasted text is inputed in one input after the other. With react, what is the right way to go about implementing a feature like this?
After componentDidMount, should I be binding and capturing the paste keyPress? Is that the right approach?
The first thing we do is create a React component called YourComponent and set it up to be default export for the file. Then, we create a function name copyCodeToClipboard that will handle our Copy to Clipboard functionality. Inside that function, we hold the <textarea> element in an el variable and select its value with the el.select () method.
There is a textbox and button on a page and button click copy the text to the clipboard user enters the text into the textbox, event handler onChange fires, and stores this into react state.
Now when we click on the button ‘Copy to Clipboard’, the function copyToClipboard gets triggered through onClick event which copies the state value to the clipboard with copy () function. Now we can copy our text anywhere by just clicking Ctrl+V key.
Consider the fact that React uses the Virtual DOM. When render occurs, it will compare the updated Virtual DOM with the previous Virtual DOM, and then only update the changed elements to the actual DOM tree. In our case, when render () is called, this.handleClick.bind (this) will be called as well to bind the handler.
Super simple example to get you started in the right direction. This would need some work before being used. Here's what it does:
There's nothing particularly tricky here. We're using local state for the sake of the example, but this could be moved to another state management implementation like Redux.
The demo uses two components:
<Input />
- to render a controlled input<App />
to render a container for the <Input />
The <App />
component handles the onPaste
event, and passes the appropriate value from the pasted data to each <Input />
component
Each <Input />
component contains a controlled <input/>
element, which consists of only a value
.
// A functional component to keep it simple
class Input extends React.Component {
constructor(props) {
super(props);
this.state = {
value: ''
};
}
handleKeyDown = (event) => {
// Handle the delete/backspace key
if (event.keyCode === 8 || event.keyCode === 46) {
this.setState({
value: ''
});
return;
}
// Handle the tab key
if (event.keyCode === 9) {
return;
}
// Handle numbers and characters
const key = String.fromCharCode(event.which);
if (Number.isInteger(Number(key))) {
this.setState({
value: key
}, () => {
// Move focus to next input
this.refs[(this.props.index + 1) % 6].focus()
});
}
}
componentWillReceiveProps = (nextProps) => {
if (nextProps.value !== this.state.value) {
this.setState({
value: nextProps.value
})
}
}
render() {
return (
<div className="inputContainer">
<input
className="input"
value={this.state.value}
onKeyDown={this.handleKeyDown}
ref={(ref) => this.refs[this.props.index] = ref}
maxLength="1"
/>
</div>
)
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
code: null
}
}
handlePaste = (event) => {
event.clipboardData.items[0].getAsString(text => {
const code = text.split("").map((char, index) => {
if (Number.isInteger(Number(char))) {
return Number(char);
}
return "";
});
this.setState({
code
});
})
}
render() {
const code = this.state.code;
return (
<div className="container" onPaste={this.handlePaste}>
<Input value={code && code[0]} index={0} />
<Input value={code && code[1]} index={1} />
<Input value={code && code[2]} index={2} />
<div className="spacer">-</div>
<Input value={code && code[3]} index={3} />
<Input value={code && code[4]} index={4} />
<Input value={code && code[5]} index={5} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("app"));
.container {
display: flex;
}
.inputContainer {
flex: 1;
border: 1px solid #cccccc;
}
.inputContainer:last-child {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.inputContainer:first-child {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.spacer {
flex: 0.3 0;
text-align: center;
height: 40px;
line-height: 40px;
font-size: 24px;
}
.input {
width: 100%;
height: 40px;
line-height: 40px;
font-size: 24px;
text-align: center;
border: none;
outline: none;
border-radius: 5px;
box-sizing: border-box;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Test Code: 135791
<div id="app"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With