【问题标题】:React JS - how to submit a form on enter or keydownReact JS - 如何在 enter 或 keydown 上提交表单
【发布时间】:2021-02-02 01:17:54
【问题描述】:

我有一个简单的 React JS 应用程序,我想添加一个搜索功能。我创建了搜索函数代码并添加了搜索组件(来自 Semantic-UI),它将搜索到的值传递给函数。

如何让它从下面的搜索组件调用函数来触发表单提交?

这是搜索组件。

   <Search
         onSearchChange={(e) => this.handleSearchChangeNew(e.target.value)}
    />

这里是搜索功能:

async handleSearchChangeNew (value) {
     console.log("value in new search: " + value)
     this.props.updateSearchString(value);

     fetch(`api/license/search/${JSON.stringify(this.props.searchString)}`, {
        credentials: 'include'})
        .then(response => response.json())
        .then(data => this.setState({
          licenses: data,
          isLoading: false,
          licensePage: data.slice(this.state.begin, this.state.end)

        }))
        .catch(() => this.props.history.push('/'));
    }

上面的函数打印从搜索框传递过来的值。

我之前组装了一个有点不雅的搜索功能,其中输入被键入到一个文本框中,并且通过按“搜索”提交功能来调用上述搜索功能。该搜索功能将根据输入框中的内容重新填充页面。它还在里面,不过我还添加了上面显示的新搜索功能代码。

作为参考,这是整个课程。

import React, { Component } from 'react';
import {  Button, ButtonGroup, Container, Table } from 'reactstrap';

import { Pagination, Search } from 'semantic-ui-react'

import AppNavbar from './AppNavbar';
import { Link, withRouter } from 'react-router-dom';
import { instanceOf } from 'prop-types';
import { withCookies, Cookies } from 'react-cookie';


class LicenseList extends Component {



  static propTypes = {
    cookies: instanceOf(Cookies).isRequired
  };

  constructor(props) {


    super(props);
    const {cookies} = props;


    this.state = {

      word: '',
      newWord: '',
      licenses: [],
      licensePage: [],
      csrfToken: cookies.get('XSRF-TOKEN'), 
      isLoading: true,
      licensesPerPage: 7,
      activePage: 1,
      begin: 0,
      end: 7
    };

    this.remove = this.remove.bind(this);
    this.btnClick = this.btnClick.bind(this);
    this.handleSearchChangeNew = this.handleSearchChangeNew.bind(this);

  }


  componentDidMount() {


   this.setState({isLoading: true});

   console.log("searchString: " + this.props.searchString);


    fetch(`/api/license/search/${this.props.searchString}`, {credentials: 'include'})
      .then(response => response.json())
      .then(data => this.setState({
        licenses: data,
        isLoading: false,
        licensePage: data.slice(this.state.begin, this.state.end)

      }))
      .catch(() => this.props.history.push('/'));
  }




   async handleSearchChange(value) {
        this.props.updateSearchString(value)

    }


   async searchFromString () {


     this.setState({isLoading: true});

     fetch(`api/license/search/${this.props.searchString}`, {
        credentials: 'include'})
        .then(response => response.json())
        .then(data => this.setState({
          licenses: data,
          isLoading: false,
          licensePage: data.slice(this.state.begin, this.state.end)

        }))
        .catch(() => this.props.history.push('/'));
    }

   async clearSearchString(value) {
       this.props.updateSearchString('');
    }



   async btnClick(
      event: React.MouseEvent<HTMLAnchorElement>,
      data: PaginationProps
    ) {
      await this.setState({activePage: data.activePage});
      await this.setState({begin: this.state.activePage * this.state.licensesPerPage - this.state.licensesPerPage});
      await this.setState({end: this.state.activePage *this.state.licensesPerPage});
      this.setState({
        licensePage: this.state.licenses.slice(this.state.begin, this.state.end),
      });
    }

  async remove(id) {
    if (window.confirm('Are you sure you wish to delete this license?')) {

    await fetch(`/api/license/${id}`, {
      method: 'DELETE',
      headers: {
        'X-XSRF-TOKEN': this.state.csrfToken,
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      credentials: 'include'
    }).then(() => {
      let updatedLicenses = [...this.state.licenses].filter(i => i.id !== id);
      this.setState({licenses: updatedLicenses});
    });
  }

  }


  download(url) {
    // fake server request, getting the file url as response
    setTimeout(() => {
      const response = {
        file: url,
      };
      // server sent the url to the file!
      // now, let's download:
      window.open(response.file);
      // you could also do:
      // window.location.href = response.file;
    }, 100);
  }

  async handleSearchChangeNewx(value) {
        this.props.updateSearchString(value);

  }


  async handleSearchChangeNew (value) {
     console.log("value in new search: " + value)
     this.props.updateSearchString(value);

     fetch(`api/license/search/${JSON.stringify(this.props.searchString)}`, {
        credentials: 'include'})
        .then(response => response.json())
        .then(data => this.setState({
          licenses: data,
          isLoading: false,
          licensePage: data.slice(this.state.begin, this.state.end)

        }))
        .catch(() => this.props.history.push('/'));
    }



  render() {
    const {licensePage, activePage } = this.state;
    const {licenses, isLoading, licensesPerPage} = this.state;
    const totalPages = Math.ceil(licenses.length / licensesPerPage);

    if (isLoading) {
      return <p>Loading...</p>;
    }

      const licenseList = licensePage.map(license => {
      return<tr key={license.id}>
        <td style={{whiteSpace: 'nowrap'}}>{license.fullName}</td>
        <td style={{whiteSpace: 'nowrap'}}>{license.requester}</td>
        <td style={{whiteSpace: 'nowrap'}}>{license.tag}</td>
        <td style={{whiteSpace: 'nowrap'}}>{license.dateCreated.substring(0, 10)}</td>
        <td style={{whiteSpace: 'nowrap'}}>{license.expiration}</td>
        <td style={{whiteSpace: 'nowrap'}}>{license.systems}</td>
        <td>

        <ButtonGroup>
            <Button size="sm" color="primary" tag={Link} to={"/licenses/" + license.id}>Edit</Button>
            <Button size="sm" color="dark" onClick={() => this.download(license.url)}>Download</Button>
            <Button size="sm" color="danger" onClick={() => this.remove(license.id)}>Delete</Button>
        </ButtonGroup>

        </td>
      </tr>
    });

    return (
      <div>
        <AppNavbar/>
        <Container fluid>
         <h3>License List</h3>
         <div className="float-left">


          <div>
            <input type="text" value={this.props.searchString} onChange={(e) =>  this.props.updateSearchString(e.target.value)} />
            <input type="submit" value="Search" onClick={() => this.searchFromString()} />
            <input type="submit" value="Clear Search" onClick={() => this.clearSearchString()} />
            <Search
                 onSearchChange={(e) => this.handleSearchChangeNew(e.target.value)}
            />

           </div>


          </div>
          <div className="float-right">


          <Button color="primary" tag={Link} to="/licenses/new">Create License</Button>
          </div>
          <Table className="mt-4">
            <thead>
            <tr>
              <th width="10%">Full Name</th>
              <th width="5%">Requester</th>
              <th width="10%">Tag</th>
              <th width="5%">Created</th>
              <th width="5%">Expiration</th>
              <th width="5%">Systems</th>
              <th width="10%">Actions</th>

            </tr>
            </thead>
            <tbody>
            {licenseList}
            </tbody>
          </Table>          
          <div>
          </div>

          <div className="col text-center">
                <Pagination
                    activePage={activePage}
                    onPageChange={this.btnClick}
                    totalPages={totalPages}
                    ellipsisItem={null}
                />
           </div>

        </Container>
      </div>
    );
  }
}

export default withCookies(withRouter(LicenseList));

【问题讨论】:

  • 此代码 sn-p 不能帮助我们帮助您。尝试添加整个组件的功能以及它在哪里使用 Semantic 的 UI 组件。做你要求的事情似乎很简单,但如果没有你的代码,我无法确定你真正需要什么。
  • 能否请您添加更多代码。看不懂

标签: reactjs form-submit


【解决方案1】:

使用原生的&lt;form&gt; 元素,一切顺利!浏览器将完成艰巨的任务。将您的输入包装在&lt;form&gt; 而不是&lt;div&gt; 中,并将您的实际表单提交处理程序传递给&lt;form onSubmit={this.handleSearchChangeNew}&gt; 上的onSubmit 侦听器。那么你需要一个event.preventDefault() 来防止页面刷新;不过,给你的输入一个name 也是一个好习惯。 &lt;form&gt; 元素会做一个基本的验证,也会处理回车键;

同时,如果您对使用 &lt;form&gt; 感到不自在,您也可以自己处理按键更改事件(就像您处理大多数原生 &lt;form&gt; 功能一样); 在您的表单逻辑所在的父 html 元素上添加 keyDown 事件侦听器;然后处理enter key code

function (event) {
    if (event.which == 13 || event.keyCode == 13) {
        // enter key had been pressed
        // submit
    }
};

编辑:如何手动处理 keydown:

<div onKeyDown={(e)=>console.log(e.keyCode)}>
  <input .... />
  <input .... />
  <Search onSearchChange={(e) => this.handleSearchChangeNew(e.target.value)} />
</div>

【讨论】:

  • 是keydown事件监听器上面的sn-p代码,还是监听器调用的代码?如果是监听器调用的代码,监听器本身是什么样子的?另外,用什么代替实际提交的“//提交”注释?
  • 使用
    标签听起来很有趣,但我不确定如何将它放入代码中。能详细点吗?
  • @JackBeNimble 在 reactjs.org 中有一个 handy article,解释了与表单相关的大部分内容以及如何将它们与 react 一起使用
猜你喜欢
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 2014-10-04
  • 2017-10-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多