I am trying to display a list of user repositories. Through the spread operator attempts to spell the object. However, I do not know if this is a good method, there are no errors in the console, but nothing appears on the screen. This is my code.
class ItemUserDetail extends React.Component {
constructor() {
super();
this.state = {
usersRepos: []
};
}
componentDidMount() {
const { user } = this.props.match.params;
const url = `https://api.github.com/users/${user}/repos`;
fetch(url)
.then(res => res.json())
.then(json => this.setState({ usersRepos: json }));
}
render() {
const Repos = this.state.usersRepos ? { ...this.state.usersRepos } : null;
return (
<div>
<p>{Repos.name}</p>
</div>
);
}
}
export default ItemUserDetail;
Since you are returning an array of repositories, your render method should look like this
render() {
const Repos = this.state.usersRepos ? this.state.usersRepos : null; // you don't need this
const { userRepos } = this.state; // destructure
return (
<div>
{userRepos.map(repo => <p key={repo.id}>{repo.name}</p>)}
</div>
);
}
Related
class MyAttendees extends React.Component {
static contextType = AuthContext;
constructor(props){
super(props);
this.state = {
barcodesData: []
}
}
componentDidMount() {
this.fetchBarcodeData()
}
fetchBarcodeData() {
const { currentUser, GetBarcodesByUser } = this.context; // getting current user logged in and a function
const uid = currentUser.uid; // uid of the user
GetBarcodesByUser(uid) // this will return a array of string containing barcodes id
.then( data => this.setState({ barcodesData: data }))
}
// force rerender
forceUpdater() {
this.forceUpdate();
}
render() {
return (
<div>
{
// trying to render the array list
// this is not rerendering even after the barcodes is updated
this.state.barcodesData.map((item) => {
console.log("item: ", item)
return <h1 key={item}>{item}</h1>
})
}
</div>
)
}
}
export default MyAttendees;
const GetBarcodesByUser = async ( uid: string ): string[] => {
const data = await getBarcodesByUser(uid);
return data;
}
export const getBarcodesByUser = async ( uid: string ): string[] => {
const result = [];
const q = query(collection(firestore, "qrcode"), where("uid", "==", uid));
onSnapshot(q, (querySnapshot): string[] => {
querySnapshot.forEach( document => {
result.push( document.id )
})
})
return result;
}
Things that I have tried
at first I was using function approach with useEffect.
I tried to use function to render array.
I tried to use the fetching function inside componentDidMount() function
Tried forceUpdate
Any of the above method is not working
Not 100% that was the entire console.log so my guess is you are mapping the wrong bit. Try changing your state to set like this
.then( response => this.setState({ barcodesData: response.data }))
From Starships I get only array of urls I would like to fetch these url adresses and get name of each starship. I tried to do it throuht map array but I probably donĀ“t know to write it. Do you have any ideas?
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {
movies:[],
starships:[],
}
}
//we fetch all data and store it to movies
async componentDidMount() {
return await fetch("https://swapi.dev/api/films/")
.then(result => result.json())
.then(data =>
this.setState({
movies: data.results
})
)
}
render(){
console.log(this.state.movies);
return (
<div className="App">
<h1>Movies</h1>
<div className="moviesList">
{this.state.movies.map((movie, index) => {
return <p key={index} >{movie.title}</p>
})}
</div>
<div className="starshipsList">
{this.state.movies.map((starship, index) => {
return <p key={index} >{starship.starships}</p>
})}
</div>
</div>
);
}
}
export default App;
You should check if the API doesn't provide another endpoint for starships as what are you trying to do isn't a best approach in my opinion.
But if it doesn't and you still need starship list, something like this could work:
async componentDidMount() {
// get movies
const moviesResult = await fetch("https://swapi.dev/api/films/");
const movies = await moviesResult.json();
// get array of all urls
const starshipsUrls = movies.results.reduce((acc, movie) => {
return acc.concat(movie.starships);
},[]);
// map over the urls and use promise.all to fetch
const starshipsResult = await Promise.all(starshipsUrls.map(url=> fetch(url)));
const starships = starshipsResult.json();
this.setState({
movies,
starships
});
}
After many attempts I fail to use arrays from https://swapi.co/api/
What I want is to use data from people and films.
I have 2 files :
App.js
import React, { Component } from "react";
import List from './List';
const API = 'https://swapi.co/api/';
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
const response = await fetch(API);
const json = await response.json();
this.setState({
data: json.data
});
};
render() {
return (
<List data={this.state} />
);
}
}
List.js
import React, { Component } from 'react';
import Person from './Person';
class List extends Component {
render() {
const { data } = this.props;
const { results } = data;
return (
<div className="flex-grow-1">
<div className="row mb-5">{results}</div>
</div>
);
}
}
export default List;
So, how do I go through that array to get what data I want to display ? I'd like to render people -> results and films -> results
results would be undefined since results is not a node within your data object... try removing the line const {results} = data and in the return map the data array:
return (
<div className="flex-grow-1">
{
data.map((results, i) => {
return (<div key={i} className="row mb-5">{results}</div>);
})
}
</div>
);
you will need the key to avoid React's unique key warning
So this code as it is now will fetch the single object that acts as a map of other urls for entities in this API. what you want to do is modify fetchData so it accepts a url. At that moment you can do an initial request to /api, read the url from the result for people and films and call fetchData again with these urls. The received data can be saved inside the state.
A example for the implementation of componentWillMount() and fetchData():
componentWillMount() {
this.fetchData('https://swapi.co/api/')
.then(res => {
this.fetchData(res.people).then(people => alert(JSON.stringify(people)));
this.fetchData(res.films).then(people => alert(JSON.stringify(people)));
});
}
async fetchData(url) {
const response = await fetch(url);
return response.json();
};
The most important change is that fetchData now returns a promise. That allows us to use the then method to use the result of the first request. You can replace the alert with a setState implementation for yourself.
I have a React component getting an item's info and returning JSX:
const detail = props => {
const service = new Services()
const detail = service.findItem(props.match.params.id)
.then(item => {
console.log(item) // logs correct details, including the title property
return item
})
.catch(err => console.log(err))
return (
<h1>{detail.title}</h1> // !! prints nothing inside the <h1> tag
)
}
As seen above, returning object logs correctly all properties, but when trying to access them through JSX, no info is shown.
There are no console errors.
Its because the detail has not yet resolved, you can have React.Component and use
export class detail extends React.Component {
state = {
item: {}
}
componentDidMount(){
const service = new Services()
const detail = service.findItem(props.match.params.id)
.then(item => {
this.setState({ item:item });
})
.catch(err => console.log(err))
}
render() {
return <h1>{this.state.item.title}</h1>
}
}
I am having difficulties mapping over this object in order to render the data on the API.
Anyone has an idea of what I may be doing wrong?
class HomePage extends Component {
state = {
weatherResults: []
};
componentDidMount() {
let obj;
fetch(`http://api.openweathermap.org/data/2.5/forecast?
id=52490&appid=${API_KEY}&q=new%20york&cnt=2`)
.then(res => res.json())
.then(results => (obj = results))
.then(() => console.log(obj));
this.setState({
weatherResults: this.state.weatherResults
});
}
render() {
return (
<div>
{this.state.weatherResults &&
this.state.weatherResults.map(data => (
<div className="container">
<p>{data.city.name}</p>
</div>
))}
</div>
);
}
}
export default HomePage;
Since the fetch request is asynchronous, you want to use setState when the request has finished to put the response in the component state.
Looking at one of the sample requests of the API it looks like you get an object as response, which has city.name in it. Instead of having weatherResults be an array, you can set it to null initially and access city.name on it when the object has loaded.
Example
class HomePage extends Component {
state = {
weatherResults: null
};
componentDidMount() {
fetch(`http://api.openweathermap.org/data/2.5/forecast?id=52490&appid=${API_KEY}&q=new%20york&cnt=2`)
.then(res => res.json())
.then(results => {
this.setState({
weatherResults: results
});
})
.catch(error => console.error(error));
}
render() {
const { weatherResults } = this.state;
if (weatherResults === null) {
return null;
}
return (
<div>
<div className="container">
<p>{weatherResults.city.name}</p>
</div>
</div>
);
}
}