Reputation: 594
I make API call using fetch().then()
...
Getting response using application/json and I want to save data from response inside html tags, return it and show to user.
From API I get 25 results but I want only first 6 (made this by using for loop).
What is inside console.log()
I want to show in code where is comment "Result should be here".
Can I and how make it happen?
Code is below.
I want to use it in Stateless/Functional Component, so without handling the state.
I'm new in all of this so please be gentle.
const Related = props => {
const url = `/artist/${props.artistId}/related`;
const getRelatedArtists = () => {
fetch(url)
.then(res => res.json())
.then(res => {
var artist, name, numFans, img;
for (let i = 0; i < 6; i++) {
artist = res.data[i];
name = artist.name;
numFans = artist.nb_fan;
img = artist.picture;
console.log(`
<div>
<p>Name: ${name}</p>
<p>Fans: ${numFans}</p>
<img src=${img} alt=${name} />
</div>
`);
}
})
.catch(err => console.log(err));
};
return (
<div>
<p>Related artists</p>
<button onClick={getRelatedArtists}>get</button>
{/* Result should be here */}
</div>
);
};
The result that I want is like this:
Upvotes: 4
Views: 7133
Reputation: 82096
React is very state and props driven - either props are passed to a component or state is maintained by one internally. In your example, without knowing more detail, it looks like your only option here would be to leverage component state. That means you can't use a stateless component, at minimum you would be looking at a PureComponent
or Component
i.e.
import React, { PureComponent } from 'react';
class Related extends PureComponent {
state = {
artists: null,
error: null
}
constructor(props) {
this.super();
this.url = `/artist/${props.artistId}/related`;
}
getRelatedArtists = async () => {
try {
const res = await fetch(this.url);
const json = await res.json();
this.setState({ artists: json.data, error: null });
} catch(e) {
console.error(e);
this.setState({ error: 'Unable to fetch artists' });
}
}
renderError() {
if (!this.state.error) return null;
return (
<span className="error">{this.state.error}</span>
)
}
renderArtistList() {
if (!this.state.artists) return null;
return this.state.artists.map((x,i) => (
<div key={i}>
<p>Name: ${x.name}</p>
<p>Fans: ${x.nb_fans}</p>
<img src=${x.picture} alt=${name} />
</div>
));
}
render() {
return (
<div>
<p>Related artists</p>
<button onClick={this.getRelatedArtists}>get</button> {this.renderError()}
{this.renderArtistList()}
</div>
);
}
}
If you are using React 16.x, then you should perhaps consider looking at using Hooks. Here's how that would look as a Function component
import React, { useState, useCallback } from 'react';
function Related(props) {
// setup state
const [artists, setArtists] = useState(null);
const [error, setError] = useState(null);
// setup click handler
const getRelatedArtists = useCallback(async () => {
try {
// fetch data from API
const res = await fetch(`/artist/${props.artistId}/related`);
const json = await res.json();
// set state
setArtists(json.data);
setError(null);
} catch(e) {
console.error(e);
setError('Unable to fetch artists');
}
}, [props.artistId]);
// setup render helper
function renderArtist(artist, key) {
return (
<div key={key}>
<p>Name: ${artist.name}</p>
<p>Fans: ${artist.nb_fans}</p>
<img src=${artist.picture} alt=${artist.name} />
</div>
);
}
// render component
return (
<div>
<p>Related artists</p>
<button onClick={getRelatedArtists}>get</button> {error}
{artists && artists.map(renderArtist)}
</div>
)
}
Upvotes: 2
Reputation: 1
while using react so you need to use the advantages that react provides to you, you should split your code and make it reusable.
secondly: for getting just a few numbers from related posts from a big array you don't need to make a loop you can just declare a variable and store in it the number of posts you need to store in it
import React, {Component} from 'react';
import Post from './post/post'
class RelatedPosts extends Component{
state = {
realted: [],
}
componentDidMount(){
const url = `/artist/${props.artistId}/related`;
fetch(url)
.then(response=>{
const relatedPosts = response.data.slice(0 ,4),
latestRelatedPosts = relatedPosts.map(post=>{
return {
post
}
})
;
this.setState({
realted: latestRelatedPosts
});
}).catch(error=>{
console.log(error)
})
}
render() {
let relatedPosts = this.state.realted.map(realtedPost=>{
return (
<Post post={realtedPost}/>
);
});
return (
<section className="Posts">
<p>Related artists</p>
{relatedPosts}
</section>
);
}
}
export default RelatedPosts;
here I created the request in componentDidMount Lifecycle because it is invoked immediately after a component is inserted into the tree and you can find more information here
and here I will create a new component to simplify the code to maintenance later if you want to change anything later and I will pass to it the data which comes from the response of my request
import React from 'react';
const post = (props) => (
<article className="relatedPost">
<h1>Name: {props.post.Name}</h1>
<h1>Fans: {props.post.numFans}</h1>
<img src={img} alt={name} />
</article>
);
export default post
Upvotes: 0