遍历对象,然后将值传递给axios函数,在react组件中呈现结果

时间:2018-12-20 03:45:06

标签: javascript reactjs axios

刚刚开始学习反应,并且需要一些有关如何循环遍历对象并将值传递到axios get请求的指针,然后将数据存储并呈现在屏幕上。

我有多个对象的数组,如下所示:

const albums = [
  {
    artist: 'Artist 1',
    album: 'Album 1'
  },
  {
    artist: 'Artist 2',
    album: 'Album 2'
  },
  {
     artist: 'Artist 3',
    album: 'Album 3'
  }
];

我想遍历相册并将这些值传递给Last.fm API的axios GET请求:

fetchAlbum(artist, title) {
  axios.get(`https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=API_KEY&artist=${artist}&album=${title}&format=json`)
  .then(res => {
    // ...
  })
}

componentDidMount() {
  this.fetchAlbum('Artist 1','Album 1');
  this.fetchAlbum('Artist 2','Album 2');
  this.fetchAlbum('Artist 3','Album 3');
}

响应返回的数据(特别是相册图像URL)是我想要用来创建相册网格(呈现为组件)的数据。我是否需要将所有这些响应数据推入状态,然后遍历并从那里渲染?还是有更简单的方法?在此先感谢!

2 个答案:

答案 0 :(得分:1)

为了同时请求多个API,可以使用axios.all函数。有关更多详细信息,请参见this link。我提供了一个基本的伪代码,以说明我们如何完成您的要求。请参考这个例子。如果您想进一步澄清,可以询问。

您可以参考this post检查setState的工作方式。

/* Basic Example */
class App extends React.Component {
  albums = [];
  baseUrl = `https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=API_KEY`;

  constructor(props) {
    super(props);
    this.albums = [{artist: "Artist 1",album: "Album 1"}, ..... ]
    this.state = {
      imageUrls: []
    }
  }


  componentDidMount() {
    axios.all(this.albums.map(u => axios.get(`{this.baseUrl}&artist=${u.artist}&album=${u.album}&format=json`)))
      .then(axios.spread((...res) => {
        // all requests are now complete
        console.log(res);

        //note res[0] will include first response, res[1] will include second response
        //now you need to manipulate data as you required in state
        const imgUrls = this.manipulationFunc(res);
        this.setState(() => {
          return {imageUrls: imgUrls }
        })

      }));
  }

  manipulationFunc(data) {
    // process image url in each response and return it
    let imageUrls = []; 
    imageUrls = getImageUrlsFromDataUsingLoopOrMap; 
    return imageUrls ;
  }

  render() {
    const {imageUrls} = this.state
    const elem = imageUrls && imageUrls[0] ? 
    (imageUrls.map(url => (
     <img src={url} />
    )): null;
    return <div> {{elem}}  </div>;
  }
}

我还没有在实际的编辑器中完成它。在出现语法错误的情况下致歉。

答案 1 :(得分:0)

您可以执行类似的操作,但是可以。您可能希望在组件状态下设置这些变量,或者在用componentWillMount()加载组件之前获取它们,然后将其设置为您的状态。这是

import React, { Component, Fragment } from "react";
import { AlbumComponent } from "/components/album";

export class ParentContainer extends Component {
  constructor() {
    super();
    this.state = {
      albums: [
        {
          artist: "Artist 1",
          album: "Album 1"
        },
        {
          artist: "Artist 2",
          album: "Album 2"
        },
        {
          artist: "Artist 3",
          album: "Album 3"
        }
      ],
      isLoading: true
    };
  }

  componentWillMount() {
    this.state.albums.forEach(album => this.fetchAlbum(album));
  }

  fetchAlbum = album => {
    axios
      .get(
        `https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=API_KEY&artist=${
          album.artist
        }&album=${album.title}&format=json`
      )
      .then(res => {
        let newState = Object.assign({}, this.state); // Duplicate your state so requests can be pushed in an array cleanly
        newState.albumMeta.push(res.data); // push the returned object to the array
        this.state.albums.length === newState.albums.length
          ? !newState.isLoading
          : newState.isLoading;
        this.setState(newState);
      })
      .catch(err => {
        console.log(error);
      });
  };

  render() {
    return (
      <Fragment>
        {!this.state.isLoading &&
          this.state.albumMeta.map(album => <AlbumComponent album={album}/>)}
        // Render your view out here based on if data is loaded
      </Fragment>
    );
  }
}