我在寻找什么?
在setState()
元素上使用input
的方法,可以使用state
立即更新onChange
。
到目前为止我做了什么?
我有两个组件BooksApp
和SearchBook
。我将result
传递给SearchBook
作为要渲染的道具。然后,我使用input
捕获onChange
元素上的更改。 onChange
正在调用我作为道具传递的方法。
React documentation说明如下,但是如果我使用回调然后在回调中调用setState()
,那么我觉得我回到了同样的情况,因为setState()
将再次出现异步:
setState()并不总是立即更新组件。它可以批量推迟更新或推迟更新。这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。相反,使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发。如果需要根据以前的状态设置状态,请阅读下面的updater参数。
有什么问题?
如果用户过快地删除input
的内容,虽然控制台中仍有console.log('empty')
,但setState()
不会运行,因此result
保持不变,不会成为一个空数组。
这是App.js
:
class BooksApp extends Component {
state = {
books: [],
result: [],
query: ''
}
updateQuery = (query) => {
this.setState({ query: query.trim() })
}
objDigger = (arr, diggers) => {
const digged = [];
diggers.forEach((d) => {
let o = {};
o = arr.filter((a) => a.id === d);
o.forEach((i) => {
digged.push(i);
})
});
return digged;
}
filterHelper = (result) => {
const resultKeys = result.map((r) => r.id)
const stateKeys = this.state.books.map((s) => s.id)
// this.objDigger(this.state.books, stateKeys)
// new books
const newKeys = _array.difference(resultKeys, stateKeys);
const newObjs = this.objDigger(result, newKeys)
// existing books
const existingKeys = _array.difference(resultKeys, newKeys)
const existingObjs = this.objDigger(this.state.books, existingKeys);
// search books
const searchObjs = newObjs.concat(existingObjs);
return searchObjs;
}
searchBook = (query) => {
this.updateQuery(query);
if (query) {
BooksAPI.search(query).then((result) => {
result = this.filterHelper(result)
if (!result.error) {
this.setState({
result,
})
}
})
} else {
console.log('empty');
this.setState(state => ({
result: []
}));
}
}
appHandleChange = (query) => {
console.log('searching');
this.searchBook(query);
}
render() {
return (
<div className="app">
<Route path="/search" render={() => (
<SearchBook
result={ this.state.result }
onChange={ this.appHandleChange }
onChangeShelf={ this.changeShelf }/>
)}>
</Route>
</div>
)
}
}
这是SearchBook
:
class SearchBook extends Component {
handleChange = (book, newShelf) => {
this.props.onChangeShelf(book, newShelf);
}
handleInputChange = (event) => {
this.props.onChange(event.target.value);
}
render() {
const { result } = this.props;
return (
<div className="search-books">
<div className="search-books-bar">
<Link
to="/"
className="close-search"
>
Close
</Link>
<div className="search-books-input-wrapper">
<input
type="text"
placeholder="Search by title or author"
onChange={ (event) => this.handleInputChange(event) }
/>
</div>
</div>
<div className="search-books-results">
<ol className="books-grid">
{result.length>0 && result.map((book) => (
<li key={book.id}>
<div className="book">
<div className="book-top">
<div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks && book.imageLinks.smallThumbnail})` }}></div>
<BookShelfChanger
shelf={book.shelf ? book.shelf : 'none'}
onChangeShelf={(newShelf) => {
this.handleChange(book, newShelf)
}}
></BookShelfChanger>
</div>
<div className="book-title">{book.title}</div>
<div className="book-authors">{book.authors}</div>
</div>
</li>
))}
</ol>
</div>
</div>
)
}
}