form.submit 回调没有被调用

IT技术 javascript reactjs react-bootstrap-typeahead
2022-07-11 01:54:46

我在我的一个应用程序中使用 react-bootstrap-typeahead module。这工作正常,除了一种情况。

如果没有结果,我无法通过按 ENTER 键提交表单。

IE; 如果react-bootstrap-typeahead 提供了建议,我可以选择其中一个选项并提交表单。在这种情况下,能够调用回调 onSubmit。

如果react-bootstrap-typeahead没有提供建议,则无法提交表单。

如果我使用 form.submit() 方法 onKeyDown 事件提交表单,表单将被提交,但是,页面会刷新而不是调用回调,这导致我完全无法控制结果。

期望的结果:如果 react-bootstrap-typeahead 提供了建议,即使没有提供建议,我也应该能够调用 onSubmit 回调。

这是我的代码。

<form ref={(form) => this.form = form} onSubmit={this.sendMessage}>
  <Typeahead
    id="rbt-example"
    dropup={true}
    ref={(typeahead) => this.typeahead = typeahead}
    onChange={this.valueChanged}
    onInputChange={this.updateQuery}
    onBlur={(e) => this.updateQuery(e.target.value, e)}
    onKeyDown={(e) => {
      // Submit the form when the user hits enter.
      if (e.keyCode === 13) {
        this.form.submit();
      }
    }}
    options={options}
    placeholder="Type your queries here..."
    renderMenu={(results, menuProps) => {
      // Hide the menu when there are no results.
      if (!results.length) {
        return null;
      }
      return <TypeaheadMenu {...menuProps} options={results} />;
    }}
  />
  <button type="submit">Submit</button>
</form>
2个回答

问题可能是调用this.form.submit(),它处理 DOM 中的表单提交(而不是 React),并且正如您所说,它使您无法控制。它正在刷新页面,因为您无法控制要调用的事件event.preventDefault()

而不是this.form.submit,您应该this.sendMessage在用户按下回车时调用。大概你正在打电话event.preventDefaultsendMessage所以你应该通过 from 传递事件onKeyDown

onKeyDown={e => {
  if (e.keyCode === 13) {
    this.sendMessage(e);
  }
}}

这样,无论是响应用户按下提交按钮还是输入,您都将以相同的方式处理表单提交。

如果您注意到我的问题中的代码,我正在处理多个事件。特别是onChangeonKeyDown

我们需要了解的几件事react-bootstrap-typeahead

  1. onChange,react-bootstrap-typeahead 会将所选对象传递给回调,而onKeyDownreact-bootstrap-typeahead 将传递事件,我将使用该事件获取值event.target.value
  2. onChange之后才会触发onKeyDown因此,如果我们想根据选定的对象进行一些操作,而onKeyDown回调中使用的值将不起作用。

为了克服这种情况,我setTimeout还使用了删除表单元素。所以我的解决方案就变成了

<Typeahead
    id="rbt-example"
    dropup={true}
    ref={(typeahead) => this.typeahead = typeahead}
    onChange={this.valueChanged}
    onInputChange={this.updateQuery}
    onBlur={(e) => this.updateQuery(e.target.value, e)}
    onKeyDown={(e) => {
      // Submit the form when the user hits enter.
      if (e.keyCode === 13) {
          if (this.timerid) {
            clearTimeout(this.timerid);
          }
          this.timerid = setTimeout(
            () => {
              this.sendMessage();
            },
            300
          );
      }
    }}
    options={options}
    placeholder="Type your queries here..."
    renderMenu={(results, menuProps) => {
      // Hide the menu when there are no results.
      if (!results.length) {
        return null;
      }
      return <TypeaheadMenu {...menuProps} options={results} />;
    }}
  />
  <button onClick={() => this.sendMessage() }>Send</button>

这样,我正在调用sendMessage方法onKeyDown并单击按钮。我还可以使用选定的选项对象。