0

I'm just learning React. I have two API calls to the backend MongoDB to pull names of vacations related to a user account. The names are saved to a JSON object and I'm trying to map through it to generate buttons on my React side but it's rendering nothing in that div. Everything else renders to the page. API calls are a mess because I thought that was the issue at first.

Profile Page

import React, { Component } from "react";
import Wrapper from "../components/Wrapper";
import { Container, Row, Col } from "../components/Grid";
import PastVacations from "../components/PastVacations";
import VacationBtn from "../components/VacationBtn"
import API from "../utils/API";

class Profile extends Component {
  state = {
    vacaIDs: [],
    vacaNames: []
  }
  componentDidMount() {
    this.getUser()
  }


  getUser = () => {
    let IDsArr = []
    API.getUser("Bill")
      .then((res) => {
        // console.log(res.data) Logs user found
        res.data.vacations.forEach((VacaIDs) => {
          let obj = {}
          obj.name = VacaIDs;
          IDsArr.push(obj)
          // console.log(items) Logs Vacation IDs          
        })
        console.log(IDsArr)
        this.setState({
          vacaIDs: IDsArr
        })
        this.getNames()
      }).catch((err) => {
        console.log(err)
      })
  }

  getNames = () => {
    let namesArr = []
    this.state.vacaIDs.forEach((names) => {
      console.log(names.name)// Logs vacation IDs
      let obj = {}
      API.getVacations(names.name).then((res) => {
        console.log(res.data.name)// Logs Vacation names
        obj.name = res.data.name;
        namesArr.push(obj)
      }).catch((err) => {
        console.log(err.response)
      })
    })
    this.setState({
      vacaNames: namesArr
    })
  }


  render() {
    return (
      <div className="">
        <div className="row justify-content-around">
          <div className="col-md-6">
            {this.state.vacaNames.map(items => (
              <VacationBtn
                name={items.name}
              />
            ))}
          </div>
          <div className="col-md-4">
            <div className="card">
              <h5 className="card-header">
                Card title
                </h5>
              <div className="card-body">
                <p className="card-text">
                  Card content
                    </p>
              </div>
              <div className="card-footer">
                Card footer
                </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Profile;

VacationBtn Component

import React, { Component } from "react";
import "./style.css";

class VacationBtn extends Component {
  render() {
    return (
      <button type="button" className="btn btn-primary">{this.props.name}</button>
    );
  }
}

export default VacationBtn;

2 Answers 2

2

Use Promise.all Your current code is iterating for API calls but setState happens before any of the api calls are resolved.

getNames = () => {
  let namesArr = [];
  const promises = [];
  this.state.vacaIDs.forEach((names) => {
    promises.push(API.getVacations(names.name));
  });

  Promise.all(promises).then((values) => {
    // do data manipulation here
    values.forEach((val) => {
      namesArr.push(val.data.name);
    });
    this.setState({
      vacaNames: namesArr,
    });
  });
};
Sign up to request clarification or add additional context in comments.

1 Comment

Worked perfectly. I guess I need to brush up on my JS as well. Thank you.
2

As @chandan_kr_jha noticed you're updating state before API is finished it's work.

A bit fancier code below with the same idea behind:

getNames = async () => {
  const promises = this.state.vacaIDs.map((names) => API.getVacations(names.name));
  const vacations = await Promise.all(promises);
  this.setState({
    vacaNames: vacations.map(v => v.data.name),
  });
};

Comments

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.