数组映射时,数组状态消失

时间:2019-06-02 12:01:35

标签: javascript arrays reactjs

我正在从NYT API获取书籍,因此useEffect运行良好。在useEffect之后,state具有一个包含书籍的数组,但是在尝试映射该数组时未显示任何内容。我做错了什么?

我试图创建newArr数组并从中显示,但也没有用。

App.js

import React, { useEffect, useState } from 'react';
import BookServer from "./book-server/book-server";
import Card from "./components/Card";

import "./App.css";

function App() {

  const[books, setBooks] = useState([]);

  useEffect(() => {
    const bookServer = new BookServer();
    const arr = bookServer.getBooks();
    setBooks(arr);
  },[]);

  return (
   <div className="content_books">
      {books ? books.map(item => {
        return <Card title={item.title} description={item.description} />
      }) : console.log(null)}

   </div>
  );
}

export default App;

BookServer.js

// import React, {useState, useEffect} from 'react';

function httpGet(url) {
  return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);

    xhr.onload = () => {
      if(xhr.status === 200) {
        resolve(JSON.parse(xhr.response));
      } else {
        let error = new Error(xhr.statusText);
        error.code = xhr.status;
        reject(error);
      }
    };

    xhr.onerror = () => {
      reject(new Error('Connection failed'));
    };

    xhr.send();
  })
}

class BookServer {
  config = {
    apiKey: 'hidden',
    url: 'https://api.nytimes.com/svc/books/v3/lists/best-sellers/history.json'
  };
  books = [];


  getFromApi = () => {
    httpGet(`${this.config.url}?api-key=${this.config.apiKey}`)
      .then(response => {
        response.results.map(item => {
          this.books.push(item);
        });
      })
      .catch(reject => {
        console.log(reject)
      });
  };

  getBooks = () => {
    this.getFromApi();
    return this.books;
  }
};

export default BookServer;

Card.js

import React from 'react';

function Card({title, description}) {
  return (
    <div className="card">
      <img src="https://s1.nyt.com/du/books/images/9780553897845.jpg" className="card-img-top" alt="Game of thrones" />
      <div className="card-body">
        <h5 className="card-title">{title}</h5>
        <p className="card-text">{description}</p>
        <a href="#" className="btn btn-primary">Buy</a>
      </div>
    </div>
  );
}

export default Card;

3 个答案:

答案 0 :(得分:0)

您不需要newArr

const[books, setBooks] = useState([]);

已经在其中指定了books。用它来映射项目。

此外,如果获取书籍是异步调用。当数组为空时,您可以执行三元操作来渲染null。这样可以防止初始循环中的标记中包含空值,并且可以对类似book.name之类的内容进行更多检查,从而导致name出现不确定的错误。


 books ? books.map(book => {}) : null;

答案 1 :(得分:0)

您需要在映射数组后返回元素,否则它将无法呈现。

import React, { useEffect, useState } from 'react';

import "./App.css";

function App() {
  const[books, setBooks] = useState([]);

  useEffect(() => {
    fetch(`https://api.nytimes.com/svc/books/v3/lists/best-sellers/history.json?api-key=${your_api_key}`,{
      method: "GET"
    })
    .then(res=>res.json())
    .then(res=>setBooks(res.results))
    .catch(err=>console.log(err));
  },[]);

  return (
   <div className="content_books">
      {books.map((item, index) => <div
       key={index}
       className="card">
        <img src="https://s1.nyt.com/du/books/images/9780553897845.jpg" className="card-img-top" alt="Game of thrones" />
        <div className="card-body">
           <h5 className="card-title">{item.title}</h5>
           <p className="card-text">{item.description}</p>
           <a href="#" className="btn btn-primary">Buy</a>
         </div>
        </div>
      )}

   </div>
  );
}

export default App;

答案 2 :(得分:0)

您必须知道lambda函数如何工作。 如果您使用的是{},则必须使用return,因为这是代码块:

new Arr.map(item => {
    return (
        <div>{item}<div>
    );
}

但是默认情况下不带{}的lambda函数使用return语句:

new Arr.map(item => (
        <div>{item}<div>
    );