Изменить фокус ввода текста с помощью реакции
Моя цель здесь состоит в том, чтобы создать форму, которая будет переходить к следующему элементу ввода при нажатии клавиши возврата и отправлять форму при последнем вводе.
Он создается для мобильных устройств, и поскольку в браузере нет возможности использовать кнопку "Далее" вместо кнопки "Перейти с клавиатуры" (дополнительную информацию об этом см. В этом ответе).
Чтобы лучше это представить, вот картинка:
Я также написал некоторый код, но суть в том, что я не могу поймать событие в нужном месте, поэтому форма сразу отправляется после возврата или, когда я предотвращаю событие, фокус меняется после того, как я нажимаю вернуть 2 раза.
Смотрите пример здесь: https://codepen.io/ofhouse/pen/Rgwzxy (я также вставил код ниже)
class TextInput extends React.Component {
constructor(props) {
super(props);
this._onKeyPress = this._onKeyPress.bind(this);
}
componentDidMount() {
if (this.props.focus) {
this.textInput.focus();
}
}
componentDidUpdate(nextProps) {
if (nextProps.focus) {
this.textInput.focus();
}
}
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
}
}
render() {
return (
<div>
<input
type="text"
onKeyPress={this._onKeyPress}
ref={input => {
this.textInput = input;
}}
/>
</div>
);
}
}
class Application extends React.Component {
constructor(props) {
super(props);
this.state = {
currentElement: 0,
};
}
_submitForm(e) {
// If I remove this preventDefault it works, but also the form is submitted --> SiteReload
e.preventDefault();
}
_changeFocus(nextElement) {
return e => {
this.setState({
currentElement: nextElement,
});
};
}
render() {
const { currentElement } = this.state;
return (
<form>
<h1>React input focus</h1>
<TextInput focus={currentElement === 0} onSubmit={this._changeFocus(1)} />
<TextInput focus={currentElement === 1} onSubmit={this._changeFocus(0)} />
<div>
<button type="submit" onClick={this._submitForm}>Submit</button>
</div>
</form>
);
}
}
ReactDOM.render(<Application />, document.getElementById('app'));
1 ответ
Я не думаю, что вы используете лучший подход, позвольте мне объяснить. Фокусировка входных данных осуществляется focus
метод родного элемента DOM. Чтобы знать, какой ввод для фокусировки на основе того, какой вход имеет текущий фокус, является логикой, которую необходимо реализовать в контейнере этих входов, Application
Компонент в вашем случае.
Я сделал несколько значительных изменений в вашем коде, и теперь он работает: CodePen
Позвольте мне объяснить это:
Прежде всего, мы препятствуем представлению keyPressed
событие ввода при нажатии клавиши 'Enter'
, чтобы предотвратить форму submit
_onKeyPress(e) {
if (e.key === 'Enter') {
this.props.onSubmit(e);
e.preventDefault();
}
}
Нам тоже не нужно componenDidMount
ни componentDidUpdate
в TextInput
все, что нам нужно, это focus
метод:
focus() {
this.textInput.focus();
}
Большинство изменений сделано в Application
составная часть. Прежде всего, нам не нужно состояние, нам действительно нужно иметь входные данные в массиве, чтобы мы могли вызывать focus
на них.
constructor(props) {
super(props);
this.inputs = [];
}
Чтобы изменить фокус, нам просто нужен индекс ввода для вызова focus
метод TextInput
составная часть:
_changeFocus(index) {
return e => {
this.inputs[index].focus();
};
}
Тогда нам нужен способ добавить входные данные в this.inputs
, ref
свойство было бы идеальным, я создал метод _addInput
в качестве помощника для этого:
_addInput(index) {
return input => {
this.inputs[index] = input;
};
}
Наконец, при рендеринге TextInput
s вы должны передать их _addInput
в ref
а также _changeFocus
в onSubmit
с соответствующими индексами:
<TextInput ref={this._addInput(0)} onSubmit={this._changeFocus(1)} />
<TextInput ref={this._addInput(1)} onSubmit={this._changeFocus(0)} />
Во-вторых TextInput
Я изменяю фокус на первый, но, возможно, отправка формы будет более полезной.