反应应用程序接收承诺而不是json对象

时间:2018-05-23 15:27:49

标签: json reactjs

我正在尝试查询应该返回与用户查询匹配的书籍的json对象的API。

问题是我在代码中得到的是一个承诺,而不是一个json对象。

在Chrome开发工具中,我可以看到我从服务器获得了一个带有json类型的200响应,而对象就是我希望收到的内容。

当我console.log查询结果时,它会作为承诺出现。

对此很新,但我的理解是,在我的searchBook组件中使用查询字符串设置SearchBooks时,我应该获取一个json对象

SearchBooks.js

import React, { Component } from 'react'
import * as BooksAPI from './utils/BooksAPI'
// import Book from './Book';

export default class SearchBooks extends Component {

    state = {
        query: ''
    }

    updateQuery = (query) => {
        this.setState(() => ({
            query: query
        }))
    }

    clearQuery = () => {
        this.updateQuery('')
    }

    searchBook = (query) => {
        return BooksAPI.search(query)
    }

    searchFromQuery = () => {
        return this.state.query.split(' ').map((b) => (
            this.searchBook(b)
        ))
    }

    render() {

        const { query } = this.state
        // const { onUpdateShelf } = this.props

        const showingBooks = query === ''
        ? 'No results'
        : this.searchFromQuery()

        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">
                  {/* <Book
                    key={book.id}
                    book={book}
                    updateShelf={onUpdateShelf} /> */}
                  </ol>
                </div>
            </div>
        )
    }
}

API Request Function

export const search = (query) =>
  fetch(`${api}/search`, {
    method: 'POST',
    headers: {
      ...headers,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query })
  }).then(res => res.json())
    .then(data => data.books)

Result of console.log(this.searchFromQuery())

[Promise]
0
:
Promise
__proto__
:
Promise
[[PromiseStatus]]
:
"resolved"
[[PromiseValue]]
:
Array(20)
length
:
1
__proto__
:
Array(0)

Request/Response Headers

// Request
POST /search HTTP/1.1
Host: reactnd-books-api.xxxxx
Connection: keep-alive
Content-Length: 13
Accept: application/json
Origin: http://localhost:3000
Authorization: 2nhixsfp
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
Content-Type: application/json
Referer: http://localhost:3000/search
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8

// Response
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
ETag: W/"78c1-CfIO/Nda/QZYUxfCqeekUjLL3SU"
Date: Wed, 23 May 2018 15:15:00 GMT
Transfer-Encoding: chunked
Content-Encoding: gzip
X-Berlioz-Country: GB
Access-Control-Allow-Headers: X-Berlioz-Country
Access-Control-Expose-Headers: X-Berlioz-Country
Strict-Transport-Security: max-age=300;

Request URL: https://xxxx.com/search
Request Method: POST
Status Code: 200 OK
Remote Address: xxxxx
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Headers: X-Berlioz-Country
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Berlioz-Country
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Wed, 23 May 2018 15:15:00 GMT
ETag: W/"78c1-CfIO/Nda/QZYUxfCqeekUjLL3SU"
Strict-Transport-Security: max-age=300;
Transfer-Encoding: chunked
X-Berlioz-Country: GB
X-Powered-By: Express
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Authorization: 2nhixsfp
Connection: keep-alive
Content-Length: 13
Content-Type: application/json
Host: reactnd-books-api.udacity.com
Origin: http://localhost:3000
Referer: http://localhost:3000/search
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
{query: "p"}
query
:
"p"

1 个答案:

答案 0 :(得分:1)

对来自res.json()的响应调用fetch会返回以JSON格式解析为请求正文的承诺。您应该做的是使用来自请求的数据设置一些状态。你可以这样做:

export default class SearchBooks extends Component {

    state = {
        query: '',
        books: []
    }

    updateQuery = (query) => {
        this.setState(() => ({
            query: query
        }))
    }

    clearQuery = () => {
        this.updateQuery('')
    }

    searchBook = (query) => {
        // Instead of returning the promise, you add the response data to the state
        BooksAPI.search(query)
         .then(books => this.setState(prevState => ({ books: prevState.books.concat(books)})));
    }

    render() {

        const { query } = this.state
        // const { onUpdateShelf } = this.props

        const showingBooks = query === ''
        ? 'No results'
        : 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">
                  {this.state.books.map(book => <Book key{book.id} book={book} updateShelf={onUpdateShelf} />)}
                  </ol>
                </div>
            </div>
        )
    }
}

这是一般的想法,只需从promise中获取值并将其设置为state。您可以根据需要对其进行扩展。