React onChange stuck in infinite loop

3th*_*1ll 5 reactjs

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>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 2

您正在渲染函数内设置状态,只要searchBook不是query空字符串。该setState()方法会触发重新渲染,但由于您是从渲染函数内部设置状态,因此它将继续调用自身。

我不明白为什么你需要这个函数在渲染内部。您希望在查询更改时搜索一本书,但查询只能根据用户输入更改,因此将函数移到那里?这是我要做的:

更改onChange={(event) => this.updateQuery(event.target.value)}为仅onChange={this.updateQuery}. 无论如何,事件都会传递给函数。

然后,将 bookapi 逻辑移至您的updateQuery函数中:

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)
      })));
}
Run Code Online (Sandbox Code Playgroud)