I am trying to create a react form that uses refs. What I need is when the user inputs a value in one input field. it should automatically focus on the next sibling element ie second input element and so on until the end of the input fields are reached and the form's value should get automatically gets saved into the state.
I am quite new to using react refs. I tried developing a basic working but is stuck on error:
TypeError: Cannot read property 'nextSibling' of undefined
Todo._handleKeyPress
22 |
23 | e.preventDefault();
24 |
> 25 | let next = this.refs[field.name].nextSibling;
| ^ 26 | if (next && next.tagName === "INPUT") {
27 | this.refs[field.name].nextSibling.focus();
28 | }
import ReactDOM from "react-dom";
import React, { Component } from "react";
import "./style.css";
class Todo extends Component {
constructor(props) {
super(props); // create a ref to store the textInput DOM element
this.state= {
}
this.textInput1 = React.createRef();
this.textInput2 = React.createRef();
this.textInput3 = React.createRef();
}
_handleKeyPress = (e, field) => {
e.preventDefault();
let next = this.refs[field.name].nextSibling;
if (next && next.tagName === "INPUT") {
this.refs[field.name].nextSibling.focus();
}
};
submitForm = () => {
}
render() {
return (
<React.Fragment>
<form onSubmit={this.submitForm}>
<input
type="number"
name={this.textInput1}
maxLength="1"
ref={this.textInput1}
onKeyPress={e => this._handleKeyPress(e, this.textInput1)}
/>
<input
type="number"
name={this.textInput2}
maxLength="1"
ref={this.textInput3}
onKeyPress={e => this._handleKeyPress(e, this.textInput2)}
/>
<input
type="number"
name={this.textInput3}
maxLength="1"
ref={this.textInput3}
onKeyPress={e => this._handleKeyPress(e, this.textInput3)}
/>
<button>Submit</button>
</form>
</React.Fragment>
);
}
}
ReactDOM.render(<Todo />, document.getElementById("root"));
I have included the demo code in the link: https://stackblitz.com/edit/react-6gsfxd . ANy kind of help is appreciated.
The second argument field
is already a reference to the input element, you don't need to call it with this.refs
.
I have made few changes in _handleKeyPress
method.
import ReactDOM from "react-dom";
import React, { Component } from "react";
import "./style.css";
class Todo extends Component {
constructor(props) {
super(props); // create a ref to store the textInput DOM element
this.state= {
}
this.textInput1 = React.createRef();
this.textInput2 = React.createRef();
this.textInput3 = React.createRef();
}
_handleKeyPress = (e, field) => {
let next = field.current.nextSibling;
field.current.nextSibling.focus();
};
submitForm = () => {
}
render() {
return (
<React.Fragment>
<form onSubmit={this.submitForm}>
<input
type="number"
name={this.textInput1}
maxLength="1"
ref={this.textInput1}
onKeyUp={e => this._handleKeyPress(e, this.textInput1)}
/>
<input
type="number"
name={this.textInput2}
maxLength="1"
ref={this.textInput2}
onKeyUp={e => this._handleKeyPress(e, this.textInput2)}
/>
<input
type="number"
name={this.textInput3}
maxLength="1"
ref={this.textInput3}
onKeyUp={e => this._handleKeyPress(e, this.textInput3)}
/>
<button>Submit</button>
</form>
</React.Fragment>
);
}
}
ReactDOM.render(<Todo />, document.getElementById("root"));
Example:
const InputForm = () => {
const focusChangeHandler = (e) => {
const { value, name } = e.target;
const [fieldName, fieldIndex] = name.split("-");
if (parseInt(fieldIndex) < 4) {
const nextfield = document.querySelector(
`input[name=field-${parseInt(fieldIndex) + 1}]`
);
// If found, focus the next field
if (nextfield !== null) {
nextfield.focus();
}
}
};
return (
<form>
<input
name="field-1"
onChange={focusChangeHandler}
type="text"
maxLength="1"
/>
<input
name="field-2"
onChange={focusChangeHandler}
type="text"
maxLength="1"
/>
<input
name="field-3"
onChange={focusChangeHandler}
type="text"
maxLength="1"
/>
<input
name="field-4"
onChange={focusChangeHandler}
type="text"
maxLength="1"
/>
</form>
);
};
export default InputForm;
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.