Home > Enterprise >  How can I make fetch calls to two different APIs and match the username from the first one to the re
How can I make fetch calls to two different APIs and match the username from the first one to the re

Time:11-05

API 'A' will give me the username. API 'B' will give me the image. I have to pass the username I get from API 'A' as an argument to API 'B' and API 'B' will then return an image assigned to that username.

I then have to display all the information from API 'A' along with the image from API 'B'.

Here is what I tried:

Parent Component

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

  export default class DataList extends Component {
   constructor(props) {
     super(props);

     this.state = {
     data: [],
     };

     console.log("constructor datalist");
    }

   componentDidMount = async () => {
     var response = await 
     fetch("https://jsonplaceholder.typicode.com/users", {
      method: "GET",
      });
     var information = await response.json();
     console.log("did mount datalist", information);
     this.setState({ data: information });
    };


    render() {
      console.log("render datalist");
      return (
       <ul>
           {this.state.data.map((info) => {
             return (
              <li key={info.username}>
                <DataItem allData={info} />
              </li>
             );
            })}
       </ul>
      );
     }

     componentDidCatch(error, info) {
     //console.log("componentDidCatch ", error, info);
      localStorage.lastError = `${error}\n 
      ${JSON.stringify(info)}`;
     }
     }

Child

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

export default class DataItem extends Component {
constructor(props) {
 super(props);

 this.state = {
  allData: { userData: this.props.allData, userImage: [] },
 };
 console.log("constructor dataitem ", this.state.allData);
 }

 componentDidMount = async () => {
  var response = await fetch(
  "https://avatars.dicebear.com/v2/avataaars/
  {{this.state.allData.userData.username}}.
   svg?options[mood][]=happy",
  {
    method: "GET",
  }
 );
var information = await response.json();
console.log("didmount dataitem", information);
this.setState({ ...this.state.allData, userImage: information 
});
 };

  render() {
  console.log("render DataItem");
   return (
  <div className="card card-style">
    <div className=" card-horizontal">
      {this.state.allData.userImage.map((info) => {
        return <DataImageItem cardDataImage={info} />;
      })}
      <div className="card-body card-body-style">
        <h2 className="card-title card-title-style">
          {this.state.allData.userData.name}
        </h2>
        <div className="info">
          <p>
            <strong>Email: </strong>
            {this.state.allData.userData.email}
          </p>
          <p>
            <strong>Phone: </strong>
            {this.state.allData.userData.phone}
          </p>
          <p>
            <strong>Company: </strong>
            {this.state.allData.userData.company.name}
          </p>
          <p>
            <strong>Website: </strong>
            {this.state.allData.userData.website}
          </p>
          <p>
            <strong>Address: </strong>
            {this.state.allData.userData.address.street},{" "}
            {this.state.allData.userData.address.suite},
            {this.state.allData.userData.address.city},{" "}
            {this.state.allData.userData.address.zipcode}
          </p>
        </div>
      </div>
    </div>
  </div>
);
}
}

DataItem's Child

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

 export default class DataImageItem extends Component {
 constructor(props) {
   super(props);
   this.state = {
    cardDataImage: this.props.cardDataImage,
   };
 }

 render() {
   return (
     <div className="img-square-wrapper p-2">
       {this.state.cardDataImage.map((image) => {
         return <DataImage imageData={image} />;
        })}
     </div>
  );
 }
}

DataImageItem's Child

import React, { Component } from "react";
export default class DataImage extends Component {
 constructor(props) {
   super(props);

    this.state = {
     imageData: this.props.imageData,
   };
 }
  render() {
   return <img className="profile-img" src= 
    {this.state.imageData} alt="" />;
  }
 }

CodePudding user response:

"https://avatars.dicebear.com/v2/avataaars/
  {{this.state.allData.userData.username}}.
   svg?options[mood][]=happy"

Should be

`https://avatars.dicebear.com/v2/avataaars/
  ${this.state.allData.userData.username}.
   svg?options[mood][]=happy`

You are using a react template string in a basic javascript string. So {{this.state.allData.userData.username}} was sent literaly.

CodePudding user response:

In the componentDidMount of your DataItem component, you'd want to inject or dynamically include the value received from the parent component as a prop, this could be accomplished using template literals, wherein you place your string value within backticks instead of single or double quotes(',""), this would then enable you to inject values using the ${} syntax.
Also, you are trying to set an image to array and then trying to map over it in DataItem component. Since you are already mapping in the parent component, the child component and its children component(s) would be rendered for each item, so it is better advised to set the userImage property to the image URL directly and send data down to other child components. So you could remove componentDidMount in your DataItem component.

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

export default class DataItem extends Component {
  constructor(props) {
  super(props);
  this.state = {
   allData: { userData: this.props.allData, userImage: 
    `https://avatars.dicebear.com/v2/avataaars/
    ${this.state.allData.userData.username}.svg?options[mood][]=happy` },
   };
   console.log("constructor dataitem ", this.state.allData);
  }
  render() {
  console.log("render DataItem");
   return (
  <div className="card card-style">
    <div className=" card-horizontal">
      
      <DataImageItem cardDataImage={this.state.userImage} />; {//Remove mapping}
      
      <div className="card-body card-body-style">
        <h2 className="card-title card-title-style">
          {this.state.allData.userData.name}
        </h2>
        <div className="info">
          <p>
            <strong>Email: </strong>
            {this.state.allData.userData.email}
          </p>
          <p>
            <strong>Phone: </strong>
            {this.state.allData.userData.phone}
          </p>
          <p>
            <strong>Company: </strong>
            {this.state.allData.userData.company.name}
          </p>
          <p>
            <strong>Website: </strong>
            {this.state.allData.userData.website}
          </p>
          <p>
            <strong>Address: </strong>
            {this.state.allData.userData.address.street},{" "}
            {this.state.allData.userData.address.suite},
            {this.state.allData.userData.address.city},{" "}
            {this.state.allData.userData.address.zipcode}
          </p>
        </div>
      </div>
    </div>
  </div>
);
}
}

DataItemImage

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

 export default class DataImageItem extends Component {
 constructor(props) {
   super(props);
   this.state = {
    cardDataImage: this.props.cardDataImage, //Contains image url
   };
 }

 render() {
   return (
     <div className="img-square-wrapper p-2">
       
         <DataImage imageData={this.state.cardDataImage} />;
        
     </div>
  );
 }
}

DataImage

import React, { Component } from "react";
export default class DataImage extends Component {
 constructor(props) {
   super(props);

    this.state = {
     imageData: this.props.imageData,
   };
 }
  render() {
   return <img className="profile-img" src= 
    {this.state.imageData} alt="" />;
  }
 }

You can also look into the official documentation for more information on template literals.

  • Related