Изменить фокус ввода текста с помощью реакции

Моя цель здесь состоит в том, чтобы создать форму, которая будет переходить к следующему элементу ввода при нажатии клавиши возврата и отправлять форму при последнем вводе.

Он создается для мобильных устройств, и поскольку в браузере нет возможности использовать кнопку "Далее" вместо кнопки "Перейти с клавиатуры" (дополнительную информацию об этом см. В этом ответе).

Чтобы лучше это представить, вот картинка:

Я также написал некоторый код, но суть в том, что я не могу поймать событие в нужном месте, поэтому форма сразу отправляется после возврата или, когда я предотвращаю событие, фокус меняется после того, как я нажимаю вернуть 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;
  };
}

Наконец, при рендеринге TextInputs вы должны передать их _addInput в ref а также _changeFocus в onSubmitс соответствующими индексами:

<TextInput ref={this._addInput(0)} onSubmit={this._changeFocus(1)} />
<TextInput ref={this._addInput(1)} onSubmit={this._changeFocus(0)} />

Во-вторых TextInput Я изменяю фокус на первый, но, возможно, отправка формы будет более полезной.

Другие вопросы по тегам