如何从 API 获取 React JS 组件中多个项目的数据

2022-01-20 00:00:00 json reactjs fetch javascript fetch-api

我正在尝试从我的 React JS 组件中的 API 获取数据.链接到 API.此 API 将填充每辆车的数量.最后一个参数 'audi' 对应于车辆制造商名称.我需要为 64 种不同的车辆获取该数据并创建动态列表项 (li),但不知道该怎么做.除 fetchCount 功能外,一切正常.

这是从../shared/vehicle_make_and_models"导入的车辆数据示例,共有 64 个护理品牌.

const veh_data = [{阿尔法罗密欧":[145",90",阿尔法6",阿尔法苏德"]},{阿斯顿马丁":[15",2升",AM Vantage",Atom",Cygnet",DB2"]},{奥迪":[100",200",A1",A2",A3",A4",A5",A6",A7"]}];

这是我的代码:

import React, { Component } from 'react';从../shared/vehicle_make_and_models"导入 { veh_data }类 ShopByMake 扩展组件 {构造函数(道具){超级(道具);this.fetchCount = this.fetchCount.bind(this);这个.state = {veh_data:veh_data,};}取数(制作){fetch('https://mysterious-journey-51969.herokuapp.com/api/vehicle-make-count/' + make).then(响应 => {返回响应.json();}).then(数据 => {让 firstKey = Object.keys(data)[0],计数 = 数据 [firstKey];console.log('make count' + count);返回计数;}).catch(err => console.log(err));}使成为() {常量车辆 = this.state.veh_data.reduce((acc, veh) => {让 make = Object.keys(veh)[0]返回 {使:[...acc.makes,<li className="mt-2"><a href="#"><img src={require('../assets/images/audi-logo.jpg')} className="img-fluid logos"/><span className="ml-4 list-text">{make} ({this.fetchCount(make)})</span></a></li>]};}, { 使:[] });返回 (

<div className="headings-div text-center text-white mt-4 mt-lg-0"><h5 className="headings">按品牌购物</h5></div><div className="mt-3" id="shopbymake"><ul className="list-unstyled">{vehicles.makes}</ul></div></div>);}}导出默认 ShopByMake;

解决方案

  1. 要同时执行请求,您可以使用 Promise.all().

  2. 当所有请求都完成后,过滤掉任何 null 响应 veh_data_with_count.filter(res=>res)

  3. 在 <上分配 veh_data_with_count 属性code>State 对象使用 setState() 将更改通知 React 并允许它在必要时更新 DOM.

import React, { Component } from "react";从axios"导入axios;//从 '../shared/vehicle_make_and_models' 导入 { veh_data }常量 veh_data = [{阿尔法罗密欧":[145",90",阿尔法6",阿尔法苏德"]},{阿斯顿马丁":[15",2升",AM Vantage",Atom",Cygnet",DB2"]},{奥迪:[100",200",A1",A2",A3",A4",A5",A6",A7"]}];类 ShopByMake 扩展组件 {构造函数(道具){超级(道具);//this.fetchCount = this.fetchCount.bind(this);这个.state = {veh_data_with_count:[]};}组件DidMount() {承诺.所有(veh_data.map(异步车=>{让 make = Object.keys(car)[0];让 res = 等待 axios.得到("https://mysterious-journey-51969.herokuapp.com/api/vehicle-make-count/" +make.split('-').join('')).catch(err => console.log(err));if (!res || !res.data) 返回空值;让 firstKey = Object.keys(res.data)[0],计数 = res.data[firstKey];返回{制作,计数};})).then(veh_data_with_count => {让 removeFails = veh_data_with_count.filter(res=> res)this.setState({ veh_data_with_count: removeFails });}).catch(err => console.log(err));}使成为() {常量车辆 = this.state.veh_data_with_count.map(({ make, count }, i) =>{返回 (<li key={i} className="mt-2"><a href="#"><img src="" className="img-fluid logos"/><跨度onClick={() =>this.fetchCount(make)}className="ml-4 列表文本">{make} {count}</span></a></li>);});返回 (

<div className="headings-div text-center text-white mt-4 mt-lg-0"><h5 className="headings">按品牌购物</h5></div><div className="mt-3" id="shopbymake"><ul className="list-unstyled">{车辆}</ul></div></div>);}}导出默认 ShopByMake;

https://codesandbox.io/s/lryq5lvn4q?moduleview=1

I am trying fetch data from API in my React JS component. Link to API. This API will populate the number count of each vehicle. The last argument 'audi' corresponds to vehicle make name. I need to fetch that data for 64 different vehicles and create dynamic list items (li) but don't know how to do that. Everything is working except fetchCount function.

Here is an example of vehicles data which is imported from '../shared/vehicle_make_and_models' there are total 64 care makes.

const veh_data = [
{ "alfa-romeo": ["145", "90", "Alfa 6", "Alfasud"] },
{ "aston-martin": ["15", "2-Litre", "AM Vantage", "Atom", "Cygnet", "DB2"]},
{ "audi": ["100", "200", "A1", "A2", "A3", "A4", "A5", "A6", "A7"] }
];

Here is my code:

import React, { Component } from 'react';
import { veh_data } from '../shared/vehicle_make_and_models'

class ShopByMake extends Component {
constructor(props) {
    super(props);

    this.fetchCount = this.fetchCount.bind(this);

    this.state = {
        veh_data: veh_data,
    };
}

fetchCount(make) {

    fetch('https://mysterious-journey-51969.herokuapp.com/api/vehicle-make-count/' + make)
            .then(response => {
                return response.json();
            })
            .then(data => {
            let firstKey = Object.keys(data)[0],
                count = data[firstKey];
            console.log('make count' + count);
            return count;
        })
        .catch(err => console.log(err)); 
  }

render() {

    const vehicles = this.state.veh_data.reduce((acc, veh) => {
        let make = Object.keys(veh)[0]

        return {
            makes: [
                ...acc.makes,
                <li className="mt-2"><a href="#"><img src={require('../assets/images/audi-logo.jpg')} className="img-fluid logos" /><span className="ml-4 list-text">{make} ({this.fetchCount(make)})</span></a></li>
            ]
        };
    }, { makes: [] });

    return (
        <div>
            <div className="headings-div text-center text-white mt-4 mt-lg-0"><h5 className="headings">Shop By Make</h5></div>
            <div className="mt-3" id="shopbymake">
                <ul className="list-unstyled">
                    {vehicles.makes}
                </ul>
            </div>
        </div>
    );
}
}

export default ShopByMake;

解决方案

  1. To perform the requests concurrently you could use Promise.all().

  2. When all requests are complete, filter out any null responses veh_data_with_count.filter(res=> res)

  3. Assign the veh_data_with_count property on the State Object using setState() to notify React of the changes and allow it to update the DOM if necessary.

import React, { Component } from "react";
import axios from "axios";
// import { veh_data } from '../shared/vehicle_make_and_models'
const veh_data = [
  { "alfa-romeo": ["145", "90", "Alfa 6", "Alfasud"] },
  { "aston-martin": ["15", "2-Litre", "AM Vantage", "Atom", "Cygnet", "DB2"] },
  { audi: ["100", "200", "A1", "A2", "A3", "A4", "A5", "A6", "A7"] }
];
class ShopByMake extends Component {
  constructor(props) {
    super(props);
    // this.fetchCount = this.fetchCount.bind(this);
    this.state = {
      veh_data_with_count: []
    };
  }
  componentDidMount() {
    Promise.all(
      veh_data.map(async car => {
        let make = Object.keys(car)[0];

        let res = await axios
          .get(
            "https://mysterious-journey-51969.herokuapp.com/api/vehicle-make-count/" +
              make.split('-').join('')
          )
          .catch(err => console.log(err));
        if (!res || !res.data) return null;
        let firstKey = Object.keys(res.data)[0],
            count = res.data[firstKey];

        return { make, count };
      })
    )
      .then(veh_data_with_count => {
        let removeFails = veh_data_with_count.filter(res=> res)
        this.setState({ veh_data_with_count: removeFails });
      })
      .catch(err => console.log(err));
  }

  render() {
    const vehicles = this.state.veh_data_with_count.map(
      ({ make, count }, i) => {
        return (
          <li key={i} className="mt-2">
            <a href="#">
              <img src="" className="img-fluid logos" />
              <span
                onClick={() => this.fetchCount(make)}
                className="ml-4 list-text"
              >
                {make} {count}
              </span>
            </a>
          </li>
        );
      }
    );

    return (
      <div>
        <div className="headings-div text-center text-white mt-4 mt-lg-0">
          <h5 className="headings">Shop By Make</h5>
        </div>
        <div className="mt-3" id="shopbymake">
          <ul className="list-unstyled">{vehicles}</ul>
        </div>
      </div>
    );
  }
}

export default ShopByMake;

https://codesandbox.io/s/lryq5lvn4q?moduleview=1

相关文章