我有一个React应用程序,其设置为向服务器发送API请求以检索与用户输入相匹配的书籍。
我遇到的问题是,只要任何查询开始输入搜索字段,应用就会进入循环,发送数百个请求,并且只有在从搜索中清除查询时才会停止。
如何在用户查询的每次更改中将其限制为一次调用?
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>
)
}
}
答案 0 :(得分:1)
你的代码在这里出错。
const showingBooks = query === ''
? books
: this.searchBook(query)
永远不要在API
函数中进行render()
调用。
相反,请在您的案例onChange
函数的updateQuery
中执行此操作。
在您的代码中,它会检查查询是否为空。如果不是,它实际上正在调用searchBook
函数,您实际上正在设置一些state
。每当state
更新后,您的React Component
都会调用render()
函数来更新视图。现在它处于循环中,这就是你的组件陷入无限循环的原因。
答案 1 :(得分:1)
只要searchBook
不是emtpy字符串,您就会使用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)
})));
}