Vishwanath B
Vishwanath B

Reputation: 89

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.

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.

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. The problem is that, if the user hits spacebar, which is an empty string, I get a HTTP 400 error, specifically this:

Error: Request failed with status code 400
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:60)

If I call .trim() on the input value, then that just prevents a user from typing anything at all. I'm kind of confused what to do right now. Also, is calling the API everytime the input value changes an expensive operation? 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>
  );
 }
}

Upvotes: 3

Views: 3651

Answers (4)

sk01
sk01

Reputation: 282

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. You should use debouncing.

Upvotes: 1

john doe
john doe

Reputation: 118

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?

Likely yes. You might want to debounce or throttle your requests

Upvotes: 1

H294
H294

Reputation: 166

I think the code should be:

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

Upvotes: 0

Dyo
Dyo

Reputation: 4464

You can replace whitespaces using the \s regex. You may also want to fetch after the state is updated (callback of 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.

Upvotes: 2

Related Questions