0

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;
3
  • did you try: let count = data[`${make}_count`]? Commented Jan 21, 2019 at 5:55
  • What is not working? any errors? Commented Jan 21, 2019 at 5:57
  • fetchCount method is no returning value of 'count' variable. Could you please solve that? Commented Jan 21, 2019 at 10:43

2 Answers 2

3
  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

Sign up to request clarification or add additional context in comments.

Comments

0

You can create an API which will return counts for all the vehicle_make_name and then populating that data according to your need.

2 Comments

Yes I have API.but I am unable to fetch. Please have a look at code
You can get all the models of the car type and then fetch counts for all the models.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.