Использование fetch для обратного вызова React API с помощью Google Books - books.map не является функцией - PullRequest
0 голосов
/ 23 октября 2018

Я работаю с 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;

1 Ответ

0 голосов
/ 23 октября 2018

Потому что ваш ответ Json не является массивом.Вам нужно вернуть response.items (или с помощью консоли вы можете проверить, что именно вы хотите, но это должен быть массив) в функции checkStatus.А затем вызвать функцию обратного вызова.

...