简体   繁体   English

在 React 中,如何防止搜索栏中出现空值?

[英]How do I prevent empty values in my search bar, in React?

So, I am building a book finder in React using Google Books API.所以,我正在使用 Google Books API 在 React 中构建一个图书查找器。

The user types the name of the book he/she wants to search, in the input field, and the value typed in the input is appended to the end of the API url.用户在输入字段中键入他/她要搜索的书名,然后将输入中键入的值附加到 API url 的末尾。

Basically, the API is called every single time the user types something in the input field, because I want display some of the results in a dropdown below the search bar.基本上,每次用户在输入字段中键入内容时都会调用 API,因为我想在搜索栏下方的下拉列表中显示一些结果。 The problem is that, if the user hits spacebar, which is an empty string, I get a HTTP 400 error, specifically this:问题是,如果用户点击空格键,这是一个空字符串,我会收到一个 HTTP 400错误,特别是这个:

Error: Request failed with status code 400错误:请求失败,状态码为 400
at createError (createError.js:17)在 createError (createError.js:17)
at settle (settle.js:19)在解决 (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:60)在 XMLHttpRequest.handleLoad (xhr.js:60)

If I call .trim() on the input value, then that just prevents a user from typing anything at all.如果我在输入值上调用.trim() ,那么这只会阻止用户输入任何内容。 I'm kind of confused what to do right now.我有点困惑现在该怎么办。 Also, is calling the API everytime the input value changes an expensive operation?另外,每次输入值更改时都调用 API 是一项昂贵的操作吗? This is what I've tried so far:这是我迄今为止尝试过的:

import React, { Component } from 'react';
import axios from 'axios';

export default class BookSearchForm extends Component {
  state = {
    searchTerm: ''
  };

  fetchBooks = () => {
    let apiURL = `https://www.googleapis.com/books/v1/volumes`;
    axios
      .get(`${apiURL}?q=${this.state.searchTerm}`)
      .then(res => console.log(res))
      .catch(err => console.log(err));
    };
  
  onChange = e => {
  this.fetchBooks();
  this.setState({ searchTerm: e.target.value });
  };

  render() {
  return (
    <div className="container">
     <form autoComplete="off">
      <input
        className="search-bar"
        type="search"
        placeholder="Search for books"
        onChange={this.onChange}
        value={this.state.searchTerm}
      />
     </form>
    </div>
  );
 }
}

You can replace whitespaces using the \\s regex.您可以使用\\s正则表达式替换空格。 You may also want to fetch after the state is updated (callback of setState) :您可能还想在状态更新后获取(setState 的回调):

  onChange = e => {
    this.setState(
      { searchTerm: e.target.value.replace(/\s/g, '') },
      () => {
        this.fetchBooks();
      }
    );
  };

.replace(/\\s/g, '') will replace all whitespaces (including tab, newline etc...) from the string by an empty char ( '' ), making whitespaces from user inputs doing nothing. .replace(/\\s/g, '')会将字符串中的所有空格(包括制表符、换行符等.replace(/\\s/g, '')替换为空字符 ( '' ),从而使用户输入中的空格无所作为。

You could validate the user input and don't allow empty strings.您可以验证用户输入并且不允许空字符串。

Also, is calling the API everytime the input value changes an expensive operation?另外,每次输入值更改时都调用 API 是一项昂贵的操作吗?

Likely yes.可能是的。 You might want to debounce or throttle your requests您可能想要去抖动或限制您的请求

You can try below code.你可以试试下面的代码。

onChange = e => {
    let value = e.target.value;
    this.fetchBooks(value.trim());
    this.setState({ searchTerm: e.target.value });
};

fetchBooks = (str) => {
    if (str) {
        let apiURL = `https://www.googleapis.com/books/v1/volumes`;
        axios
            .get(`${apiURL}?q=${str}`)
            .then(res => console.log(res))
            .catch(err => console.log(err));
    }
};

Yes, calling API on every input change is expensive.是的,在每次输入更改时调用 API 都很昂贵。 You should use debouncing.您应该使用去抖动。

I think the code should be:我认为代码应该是:

 onChange = async (e) => {
   await this.setState({ searchTerm: e.target.value });
   this.fetchBooks();   
  };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM