Accessing nested JSON data in React Component - javascript

Hi i am just starting to learn react as a side project.
Im using an express backend to call an api that returns some JSON to my component. I cant seem to access the nested array to iterate over and display.
import React, { Component } from 'react';
import '../../app.css';
export class Table extends Component {
constructor(props) {
super(props);
this.state = {
jsonItems: [],
isLoaded: false
}
}
componentWillMount() {
this.renderMyData();
}
renderMyData() {
fetch('/api/nfl')
.then(res => res.json())
.then(json => {
this.setState({
jsonItems: JSON.parse(json),
isLoaded: true
})
})
}
render() {
console.log(this.state.jsonItems.fullgameschedule);
return (
<table>
<thead>
<tr>
<th>Test 1</th>
<th>Test 2</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
)
}
}
Json output:
{
"fullgameschedule": {
"lastUpdatedOn": "2018-08-24 2:55:41 PM",
"gameentry": [
{
"id": "43306",
"week": "1",
"scheduleStatus": "Normal",
"originalDate": null,
"originalTime": null,
"delayedOrPostponedReason": null,
"date": "2017-09-07",
"time": "8:30PM",
"awayTeam": {
"ID": "73",
"City": "Kansas City",
"Name": "Chiefs",
"Abbreviation": "KC"
},
"homeTeam": {
"ID": "50",
"City": "New England",
"Name": "Patriots",
"Abbreviation": "NE"
},
"location": "Gillette Stadium"
}
]
}
}
jsonItems gets populated (as shown in my react dev tools). but i cant seem to iterate over the json array "gameentry"
I can print out {this.state.jsonItems.fullgameschedule} , but i cant access it any further for example {this.state.jsonItems.fullgameschedule.gameentry} or gameentry[0] without the error message:
Cannot read property 'gameentry' of undefined
Which at first i thought was because of js being asynchronous that it was loading the component before it rendered, so i changed componentDidMount() to componentWillMount() and that should handle that. How can i access the array list and iterate over to display it to the component? or just a general point in the right direction.
EDIT: How im getting the data.
var options = {
url: url,
auth: {
user : 'xxx',
password : 'xxx',
}
}
app.get('/api/nfl', function (req, res) {
request(options, function (err, response, body){
if (err) {
console.log(err);
}
res.send(JSON.stringify(response.body));
})
});

As you thought since data is coming in an asynchronous way, you need to handle it somehow. When you try to get a property from an undefined object, you get an error like yours. So, you should use conditional rendering.
Before that, using componentWillMount instead of componentDidMount does not work since render does not wait for any of these two methods to finish its jobs. Actually, componentWillMount will be deprecated, so go with componentDidMount for the asynchronous operations.
Since you haven't shared the code how have you tried to get the data I'm giving a blind suggestion here.
render() {
console.log(this.state.jsonItems.fullgameschedule);
return this.state.jsonItems.fullgameschedule && (
<table>
<thead>
<tr>
<th>Test 1</th>
<th>Test 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>{this.state.jsonItems.fullgameschedule.lastUpdatedOn}</td>
</tr>
</tbody>
</table>
)
}
This is just an example. You can change it according to your needs.

Related

How to nest 3 map loop functions in ReactJS

I've been researching with no success. The answers I'm finding resolve 2 nested loops on react (with map) and I have 2 loops working already. My problem is that I need 3 of them, and I am getting errors on the third even if I have been using the same structure.
Json looks something like this:
{
"Table": [
{
"Power": "20HP",
"Count": "5",
"Vehicles": [
{
"Code": "T01-01",
"Hours": [
{
"Hour": "5:00",
"Status": "1"
},
{
"Hour": "6:00",
"Status": "2"
}
]
},
{
"Code": "T01-01",
"Hours": [
{
"Hour": "5:00",
"Status": "1"
},
{
"Hour": "6:00",
"Status": "2"
}
]
}
]
}
]
}
I have an object called table, which has an array of elements (different vehicle power types like 10 hp, 20 hp...), and each power has a set of vehicles. Finally, each vehicle has an array of hours with a status.
I want an HTML table with the power on de first column, Vehicle code on the second column and the hours on the next X columns (24).
My current code works only until second loop. On the third, I get something about "Parsing error: Unexpected token, expected ","" on VS Code.
My react code within the render is the following:
{this.state.report.Table.map((d, idx) => (
<tr>
<td style={{border:"1px solid"}} >{d.Power}</td>
{d.Vehicles.map((n, idy) => (
<td style={{border:"1px solid"}}>{n.Code}</td>
***************
{n.Hours.map((h, idz) => (
<td className={classes.available}></td>
))}
****************
))}
</tr>
))}
If I remove the code within the ***, it works, but with the third loop It does not. The error on VS Code prompts on the beginning of the third loop, in "{n."
Thanks in advance for your help, let me know if I missed something or if you need more details. Im sure I am missing a code rule, as you can imagine from my question, I'm not fluent with React.
The only overt thing I see missing is the middle mapping needs to return a single node.
{this.state.report.Table.map((d, idx) => (
<tr key={idx}>
<td style={{border:"1px solid"}} >{d.Power}</td>
{d.Vehicles.map((n, idy) => (
<React.Fragment key={indy}> //<-- return single node from map here
<td style={{border:"1px solid"}}>{n.Code}</td>
{n.Hours.map((h, idz) => (
<td key={idz} className={classes.available}></td>
))}
</React.Fragment>
))}
</tr>
))}

Trying to display a table with data from API, array inside JSON Object ANGULAR

I'm working in a project to help a friend, so most of the code in the services and the backend was already there, so I've been struggling with the structure and sometimes I get lost.
Here's my problem
This is the structure of the data on the API:
{
"title": "",
"iconURL": ",
"linkedRightsIDs": [
""
],
"linkedRights": [
{
"id": ,
"creationDate": "",
"sections": [
"women"
],
"defLanguage": "en",
"countryApplied": "united states",
"statesApplied": [
"all"
],
"title": "",
"translations": [
"en"
],
"disable": false,
"content": null
}
]
}
What I'm trying to achieve, is to make a table inside my component using the LinkedRights data. Right now, this structure only have 1 linkedRight (I deleted the data inside for privacy)
Anyways, here's the method regarding the service and model in my component.ts:
onModelLoadedAsync() {
super.onModelLoadedAsync();
if (this.mode == 'create') {
this.model = LocalityInfo;
} else {
if (this.model.iconURL){
this.imageSrc = this.model.iconURL;
}
}
if(this.mode == 'edit'){
const data= Object.entries(this.model.linkedRights); //this is me just testing
console.log(data);
}
}
here's the html of the table I'm trying to display, this is and edit route so there's a query param for the id in this view
<div class="table-responsive">
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th>Title</th>
<th>Sections</th>
<th>States</th>
<th>Enabled</th>
<th>Creation Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of data">
<td>{{item.title}}</td>
<td>{{item.sections}}</td>
<td>{{item.statesApplied}}</td>
<td>{{!item.disabled}}</td>
<td>{{item.creationDate}}</td>
</tr>
</tbody>
</table>
</div>
</div>
What I was trying to do, was to convert the JSON into an array so I could display it since there's an error that shows on the console that said this:
core.js:6456 ERROR Error: Cannot find a differ supporting object '[object Object]' of type'object'. NgFor only supports binding to Iterables such as Arrays.

Data value not showing up from JSON file at html page after submitting form

Hi everyone out there I require some assistance about Axios & VUE after submitting a form in my webpage i was redirected back to this page. Before the form was submitted the "purposeofvisit" was not empty at the html file but after submitting the form and redirected back to the html page It is empty. I am trying to access the nested object "purposeofvisit" value
let patients = new Vue({
el: "#patients",
data: {
patients: [],
},
mounted: function () {
axios
.get("http://localhost:3000/patients")
.then((response) => {
userParticulars = response.data;
this.patients = userParticulars;
console.log(this.purposeofvisit);
})
.catch((error) => {
console.log(error);
});
},
});
<tbody v-for="(user, index) in patients" :key="index">
<tr>
<td>{{user.appointments[0].purposeofvisit}}</td>
</tr>
</tbody>
This is the JSON file i am accessing
{
"patients": [
{
"id": 1,
"name": "John",
],
"appointments": [
{
"purposeofvisit": "Consultation",
}
]
}
Thee appointments has nested arrays. You could try accessing nested arrays.
user.appointments[0][0].purposeofvisit

how to access obj from json in React?

Api Respose :-
[
{
"System Name": "Name1",
"Primary Sensor": "WWWW",
"Mean Wind Speed": "6.23 m/s",
"Status": 1,
"mws_number": 44,
"DRR (%)": "100",
"drr_number": 100
},
{
"System Name": "Name 2",
"Primary Sensor": "SSSS",
"Mean Wind Speed": "4.2 m/s",
"Status": 2,
"mws_number": 6,
"DRR (%)": "100",
"drr_number": 100
}
]
My Code ->
class Home extends Component {
state = {
items:[],
isLoading:false
}
componentDidMount() {
// api
fetch('http://api.url', {
method: 'POST',
body:
JSON.stringify({"Authentication":'token'})
}).then(data => data.json() )
.then(res =>{
this.setState({isLoading:true,
items:res,}
)
});
}
render() {
return (
<>
{console.log(this.state.items[0])} // getting o/p - first obj of array
{console.log(this.state.items[0].Status)} // getting Error undef Status
{console.log(this.state.items.Status[0])} // same error undef status
</>
)
export def ....
This is my complete piece of code... I can't add api url as it is not public api :(
I want to access this data inside of the array =>(Status, System Name, etc)
how can i fetch this !!
Here, console.log(this.state.items[0]); is getting called two times;
- When the page first loads and API request is not finished.
- After the API request finishes and you call this.setState
Solution would be to check that items' length is greater than 0 before trying to use it. Try changing console.log(this.state.items[0]); to this:
if (this.state.items.length > 0) { console.log(this.state.items[0].Status); }
I would suggest you to use componentWillMount() instead of componentDidMount() becuase componentWillMount() happens before render while componentDidMount() happens after the first render.May be that help.

retrieve the data from json folder with angularjs

Hello I try to make a angularjs application so i retrieve a data from a json folder but it's display lik this ["adventure","sci-fi"]
how can I please remove [" "] from this ["adventure","sci-fi"]
this is my json folder
[
{
"title": "Interstellar",
"genre": [
"adventure",
"sci-fi"
],
"watched": false
},
{
"title": "Inception",
"genre": [
"action",
"mystery",
"sci-fi"
],
"watched": true
}
]
and this my service.js
var app = angular.module('appMovies', [] );
app.service('moviesService', function($http,$q){
var deferred =$q.defer();
$http.get('movies.json').then(function (data)
{
deferred.resolve(data);
});
this.getPlayers = function ()
{
return deferred.promise;
}
})
and this my controller
app.controller('appcontrolles', function($scope,moviesService){
var promise = moviesService.getPlayers();
promise.then(function(data)
{
$scope.players =data.data;
console.log($scope.players);
});
})
and this is my index.html
<table class="table table-striped">
<thead>
<tr>
<th>title</th>
<th>genre</th>
<th>watched</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="movie in players | filter : genre |filter: search.genre |filter : watched ">
<td>{{movie.title}}</td>
<td>{{movie.genre}}</td>
<td><input type="checkbox" name="vu", ng-model="movie.watched",value="true"></td>
</tr>
</tbody>
</table>
thanks for your help
Since movie.genre is an array, when you just put {{movie.genre}}, Angular outputs the value as a string representing an array: ["adventure","sci-fi"].
If you want a simple comma-delimited list of values, you could use the .join() function of an array to create a string with a specify delimiter, like ", ", like so:
<td>{{movie.genre.join(", ")}}</td>
Alternatively, if you want more complex DOM around it, then you could ng-repeat over that array:
<td><span ng-repeat="genre in movie.genre">{{genre}}</span></td>
Off Topic:
You don't need to use $q.defer with something that already returns a promise, like $http - you can just return that promise, and so your service could be simplified to:
app.service('moviesService', function($http){
this.getPlayers = function()
{
return $http.get('movies.json');
}
});
$q.defer is used when you are trying to convert a non-promise async function of some third-party service, for example, which uses on-success and on-error handlers.

Categories

Resources