I have a React app that is set up to send an API request to a server to retrieve books that match the user's input.
The problem I have is that as soon as any query begins to be typed into the search field the app goes into a loop, sending hundreds of requests and is only stopped when the query is cleared from the search.
How can I limit it to one call per change in user query?
import React, { Component } from 'react'
import * as BooksAPI from './utils/BooksAPI'
// import Book from './Book';
export default class SearchBooks extends Component {
state = {
query: '',
books: []
}
updateQuery = (query) => {
this.setState(() => ({
query: query
}))
}
clearQuery = () => {
this.updateQuery('')
}
searchBook = (query) => {
if(query.length > 0)
BooksAPI.search(query)
.then(books => this.setState(currentState => ({
books: currentState.books.concat(books)
})));
}
render() {
const { query, books } = this.state
// const { onUpdateShelf } = this.props
const showingBooks = query === ''
? books
: this.searchBook(query)
return(
<div className="search-books">
<div className="search-books-bar">
<a className="close-search" >Close</a>
<div className="search-books-input-wrapper">
<input
type="text"
placeholder="Search by title, author or subject"
value={query}
onChange={(event) => this.updateQuery(event.target.value)}
/>
</div>
</div>
<div className="search-books-results">
<ol className="books-grid">
<li>
{/* { showingBooks.map((book) => (
<Book
key={book.id}
book={book}
updateShelf={onUpdateShelf} />
))} */}
</li>
</ol>
</div>
</div>
)
}
}
You are setting the state inside your render function with searchBook
whenever query
isn't an emtpy string. The setState()
method triggers a re-render but since you are setting the state from inside the render function, it will keep calling itself.
I don't see why you need this function to be inside the render anyway. You want to search for a book whenever the query changes, but the query can only change on user input, so move the function there? Here is what I would do:
Change onChange={(event) => this.updateQuery(event.target.value)}
to just onChange={this.updateQuery}
. The event is passed to the function anyway.
Then, move your bookapi logic to your updateQuery
function:
updateQuery = (e) => {
if(e.target.value.length > 0)
BooksAPI.search(query)
.then(books => this.setState(currentState => ({
query: e.target.value,
books: currentState.books.concat(books)
})));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With