简体   繁体   中英

How can I make fetch calls to two different APIs and match the username from the first one to the respective username of the 2nd one?

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="" />;
  }
 }
"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.

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 , 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 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>
);
}
}

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>
  );
 }
}

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM