Я работаю с React и API Google Книг над созданием веб-приложения.Я хочу, чтобы книги можно было искать через API книг Google.Когда мой запрос на выборку попадает в API Google Books, я получаю успешное возвращение, но обратный вызов не анализирует JSON, и я получаю сообщение об ошибке: «Unhandled Rejection (TypeError): books.map не является функцией», полученной из моего компонентаэто предназначено, чтобы показать результаты поиска.Кажется, что проблема исключительно между запросом на выборку и функцией HandleSearchChange в компоненте, где функция NewSearch.search инициирована и состояние установлено.Запрос на выборку возвращает данные, но, кажется, останавливается без разбора ответа - ответ уже возвращается в json - см. https://www.googleapis.com/books/v1/volumes?q=flo.
Любая помощь будет принята с благодарностью!
Вот запрос на выборку:
function search(query, cb) {
return fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}`, {
method: 'get',
headers: {
'Content-Type': 'application/json'
},
success: function(response) {
console.log(response)
}
})
.then(checkStatus)
.then(parseJSON)
.then(cb);
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(`HTTP Error ${response.statusText}`);
error.status = response.statusText;
error.response = response;
console.log(error);
throw error;
}
function parseJSON(response) {
return response.json();
return console.log(response.json())
}
const NewSearch = { search };
export default NewSearch;
Вот этот компонент:
import react from 'react';
import React, { Component } from 'react';
import NewSearch from '../actions/NewSearch';
const MATCHING_ITEM_LIMIT = 25;
class SearchBooks extends Component {
constructor(props) {
super(props);
this.state = {
books: [],
showRemoveIcon: false,
searchValue: '',
};
this.handleSearchChange = this.handleSearchChange.bind(this);
}
handleSearchChange = (e) => {
let value = e.target.value;
if (this._isMounted) {
this.setState({
searchValue: value,
[e.target.name]: e.target.value,
});
}
if (value === '') {
this.setState({
books: [],
showRemoveIcon: false,
});
} else {
this.setState({
showRemoveIcon: true,
});
NewSearch.search(value, (books) => {
this.setState({
books: books
//books: books.slice(0, MATCHING_ITEM_LIMIT),
});
});
}
};
handleSearchCancel = () => {
this.setState({
books: [],
showRemoveIcon: false,
searchValue: '',
});
};
componentDidMount() {
this._isMounted = true
}
componentWillUnmount() {
this._isMounted = false
}
render() {
const { showRemoveIcon, books } = this.state;
const removeIconStyle = showRemoveIcon ? {} : { visibility: 'hidden'};
const bookRows = books.map((book, idx) =>(
<tr>
<td>{book.volumeInfo.title}</td>
<td>{book.volumeInfo.authors[0]}</td>
<td>{book.volumeInfo.description}</td>
</tr>
));
return (
<div id='book-search'>
<table className='ui selectable structured large table'>
<thead>
<tr>
<th colSpan='5'>
<div className='ui fluid search'>
<input
className='prompt'
type='text'
placeholder='Search books...'
value={this.state.searchValue}
onChange={this.handleSearchChange}
/>
<i className='search icon' />
</div>
<i
className='remove icon'
onClick={this.handleSearchCancel}
style={removeIconStyle}
/>
</th>
</tr>
<tr>
<th className='eight wide'>Title</th>
<th>Authors</th>
<th> Description</th>
</tr>
</thead>
<tbody>
{bookRows}
</tbody>
</table>
</div>
);
}
}
export default SearchBooks;