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.