I am practicing pulling data from an API using React and can't seem to figure out how to pull more than just one page of data.
"info": {
"count": 493,
"pages": 25,
"next": "https://rickandmortyapi.com/api/character/?page=2",
"prev": ""
},
"results": [
{
"id": 1,
"name": "Rick Sanchez",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
},
{
"id": 2,
"name": "Morty Smith",
"status": "Alive",
"species": "Human",
"type": "",
"gender": "Male",
That is how the JSON data is structured and there are 20 people per page. I'm thinking it has something to do with using .com/API/character/next path somehow but can't wrap my head around it due to inexperience. This is my call in the App.js file.
function App() {
const [characters, setCharacters] = useState([]);
useEffect(() => {
async function fetchChar() {
let res = await fetch("https://rickandmortyapi.com/api/character/")
let data = await res.json();
setCharacters(data.results);
}
fetchChar();
}, [])
This is how I return like this in my Characters.js component file (Using semantic-UI-react). This has the first 20 characters show up on the page.
return(
<div>
<h1>People</h1>
<Grid columns={4}>
{data.map((characters, i) => {
return (
<Grid.Column key={i}>
<Card>
<Card.Content>
<Card.Header>{characters.name}</Card.Header>
<Card.Description>
<strong>Status</strong>
<p>{characters.status}</p>
I feel like there should be an easier way to pull from multiple pages, but after about 3 hours of research I still can't figure it out.
Is there a way to pull all 493 characters from all 25 pages or will I have to make 25 different fetch calls?
You're getting paginated results from the API. Either you need to use an API call that returns the entire data set (if it exists), OR you need to make 25 calls. You would just keep fetching with the value of next, adding to the array of data you're collecting until next presumably is empty and the calls would stop.
do a Promise.all on the rest of the pages
async function fetchChar() {
let res = await fetch("https://rickandmortyapi.com/api/character/");
let data = await res.json();
const restOfThepages = await Promise.all(
Array(data.info.pages - 1)
.fill(0)
.map(i =>
fetch(`https://rickandmortyapi.com/api/character/?page=${i + 2}`).then(res => res.json()).then(d => d.results)
)
);
const flattenedData = restOfThepages.reduce((acc, d) => [...acc, ...d], []);
return [...data.results, ...flattenedData];
}
Related
I can't reach my returned JSON data value. I'm using get method for reaching and server returns the JSON with 200 but when I try to reach JSON value it gives error.
My JSON:
{
"user": [
{
"id": 2,
"userName": "Mehmet",
"email": "personal#test.com",
"sys_role": 3,
"tckn": "00000000000",
"fk_parkID": 81
}
],
"parks": [
{
"parkID": 1,
"parkName": "Park Name",
"latitude": 42,
"longitude": 29,
"fk_regionID": 2
}, // 107 more parks like the up one.
]
}
I've tried this for reaching "userName" value from "user".
var selectedUserInfo;
var parksInfo;
selectUser(id) async { // This is selecting a person for doing some process on his/her account.
var result = CallApi().getData('admin/user/${id}', _setHeaders());
selectedUserInfo = jsonDecode(result.body)["user"][0]["userName"];
parksInfo = jsonDecode(result.body)["parks"];
setState(() {
});
}
When I
print(selectedUserInfo)
it returns null.
Your getData() method is probably an asynchronous method (Future).
If you don't wait for it, the result will be null, so the selectedUserInfo.
You should add the await keyword like this :
var result = await CallApi().getData('admin/user/${id}', _setHeaders());
I hope that will solve your issue
I am trying to list the server response , but some mistake is their in my code about accessing nested json..Following is the structure of json
Updated:
{
"child": [],
"courses": [{
"data": {
"name": "Student 1",
"date_created": 1514610451,
"total_students": 4,
"seats": "",
"start_date": false,
"categories": [{
"name": "Subject",
"slug": "Subject"
}],
"intro": {
"id": "1",
"name": "Main Admin",
"sub": ""
},
"menu_order": 0
},
"headers": [],
"status": 200
}]
}
And my react part is
render(){
return this.state.course.map(course =>
<Text style={styles.userStyle}>{course.courses.data.map(datas => datas.name)}</Text>
);
}
Please help me to figure out the mistake.I am getting this.state.course.map is not a function.My fetch request is as follows
state= {course:[]};
componentWillMount(){
fetch('https://www.mywebsite.com/' + this.props.navigation.state.params.id)
.then((response) => response.json())
.then((responseData) => this.setState({course: responseData}))
}
So you would need to show us how this.state is set, but if you're doing something like this.setState(jsonObject), the property you are looking for seems to be this.state.courses. This would access the array of courses. However, in the subsequent lines you try to access course.courses, which suggests you're setting the state like this.seState({course: jsonObject}) so it's not clear.
I'd say if you fix the first problem, you'll immediately hit another one because it doesn't look like data is an array but an object, so trying to call map on it is unlikely to do what you want (unless you've been playing with prototypes).
EDIT:
In response to the new info, I recommend the following:
render(){
if(this.state.course && this.state.course.courses) {
return this.state.course.courses.map(course =>
<Text style={styles.userStyle}>{course.data.name}</Text>
);
} else {
return [];
}
}
Im building a React app and I have a quite complex JSON file where I need to find and output certain values of an object in an array.
Im trying to output all my people from my JSON, they look something like this:
people: [
{
"id": 1,
"email": "Sincere#april.biz",
"address": [
{
"street": "Kulas Light",
"type": "house",
"attribute": {
"sketch": "sketch.jpg",
"photo": "photo.jpg"
}
},
{
"street": "Lorem Ipsum",
"type": "apartment",
"attribute": {
"sketch": "sketch.jpg",
"photo": "photo.jpg"
}
}
]
}
]
I have no problem to output the email, doing it like so:
var App = React.createClass({
getInitialState: function () {
return {
results: {}
}
},
componentDidMount() {
fetch(REQUEST_URL) // fetch from API, returns JSON
.then(res => res.json())
.then(data => {this.setState(
{ results: data.people}
);
})
},
renderResult : function(key){
return <Result key={key} index={key} details={this.state.results[key]}/>
},
render : function() {
return (
<ul>
{Object.keys(this.state.results).map(this.renderResult)}
</ul>
)
}
});
var Result = React.createClass({
render : function() {
return (
<li>
{this.props.details.email}
<img src="{this.props.details.address.type=house.attribute.photo}"/>
</li>
)
}
});
ReactDOM.render(App, document.querySelector('#app'));
However, now I need to output "photo" but only for "type": "house". I tried this but no luck, well aware that this is way off. Im quite new to handling JSON data and React and Google hasn't helped me even after a few hours of trying to solve this.
The .address property isn't an object but an array of objects so
.type is not available directly on .address:
this.state.results.people.address.type
// .type property doesn't exist on array
Solution:
You can use Array.prototype.filter on .address to obtain an array of objects that have a property type whose value is "house":
var houseAddresses = this.state.results.people.address.filter(function(value){
return value.type === "house";
});
Here, houseAddress will be an array of objects whose type value is 'house".
You can then loop through the array to create the relevant JSX using for, Array#forEach or Array#map. The following example uses Array#map:
const houseImgTags = houseAddresses.map(function(house, index){
return (
<img
src={house.attribute.photo}
key={'house'+index}
/>
);
});
(A key was added here in case there are more than one instance of a house object)
You can simply write.
<img src={this.states.results.address.type==="house"?house.attribute.photo : otherwise_photo}/>
Basically this would compare address.type is house or not,then return the result corresponded.
I am looking for best solution how to work with JSON in my angular2 app.
My JSON is:
{
"rightUpperLogoId": {
"id": 100000,
"value": ""
},
"navbarBackgroundColorIdCss": {
"id": 100001,
"value": ""
},
"backgroundColorIdCss": {
"id": 100002,
"value": ""
},
"translationIdFrom": {
"value": "90000"
},
"translationIdTo": {
"value": "90055"
}
}
This JSON is something like configuration file for UI of app. In my application, I want to get id from rightUpperLogoId, it is 100000. With this id I need to do GET task on my backend REST api and the returned value I would like to set to value. Thank you
You could leverage Rx operators like the flatMap one with Observable.forkJoin / Observable.of.
Here is a sample:
this.http.get('config.json')
.map(res => res.json())
.flatMap(config => {
return Observable.forkJoin(
Observable.of(config),
// For example for the request. You can build the
// request like you want
this.http.get(
`http://.../${config.rightUpperLogoId.id}`)
);
})
.map(res => {
let config = res[0];
let rightUpperLogoIdValue = res[1].json();
config.rightUpperLogoId.value = rightUpperLogoIdValue;
return config;
})
.subcribe(config => {
// handle the config object
});
This article could give you more hints (section "Aggregating data"):
http://restlet.com/blog/2016/04/12/interacting-efficiently-with-a-restful-service-with-angular2-and-rxjs-part-2/
I would like to display all of my recent commit messages from github on a website. Is this possible?
To get the public events of a user, you should use the /users/:user/events endpoint (Events performed by a user):
curl https://api.github.com/users/IonicaBizau/events
This will give you back a JSON response like this:
[
{
"type": "IssueCommentEvent",
...
}
{
"id": "3349705833",
"type": "PushEvent",
"actor": {...},
"repo": {...},
"payload": {
"push_id": 868451162,
"size": 13,
"distinct_size": 1,
"ref": "refs/heads/master",
"head": "0ea1...12162",
"before": "548...d4bd",
"commits": [
{
"sha": "539...0892e",
"author": {...},
"message": "Some message",
"distinct": false,
"url": "https://api.github.com/repos/owner/repo/commits/53.....92e"
},
...
]
},
"public": true,
"created_at": "2015-11-17T11:05:04Z",
"org": {...}
},
...
]
Now, you only need to filter the response to include only the PushEvent items.
Since you want to display these events on a website, probably you want to code it in javascript. Here is an example how to do it using gh.js–an isomorphic GitHub API wrapper for JavaScript/Node.js written by me:
// Include gh.js
const GitHub = require("gh.js");
// Create the GitHub instance
var gh = new GitHub();
// Get my public events
gh.get("users/IonicaBizau/events", (err, res) => {
if (err) { return console.error(err); }
// Filter by PushEvent type
var pushEvents = res.filter(c => {
return c.type === "PushEvent";
});
// Show the date and the repo name
console.log(pushEvents.map(c => {
return "Pushed at " + c.created_at + " in " + c.repo.name;
}).join("\n"));
// => Pushed at 2015-11-17T11:05:04Z in jillix/jQuery-json-editor
// => Pushed at 2015-11-16T18:56:05Z in IonicaBizau/html-css-examples
// => Pushed at 2015-11-16T16:36:37Z in jillix/node-cb-buffer
// => Pushed at 2015-11-16T16:35:57Z in jillix/node-cb-buffer
// => Pushed at 2015-11-16T16:34:58Z in jillix/node-cb-buffer
// => Pushed at 2015-11-16T13:39:33Z in IonicaBizau/ghosty
});