I have an object like:
export const contact = {
_id: "1",
first:"John",
name: {
first:"John",
last:"Doe"
},
phone:"555",
email:"john#gmail.com"
};
I am reading it like
return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact._id}</h1>
</div>
)
in this scenario I am getting expected output.
return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact.name.first}</h1>
</div>
)
But when I read the nested property I am getting error like
Uncaught TypeError: Cannot read property 'first' of undefined
How to read these king of nested objects in react? Here is my source
Three things you need to address here:
this is your contacts-data and i don't see any first property within the name object:
export const contacts = {
"name": "mkyong",
"age": 30,
"address": {
"streetAddress": "88 8nd Street",
"city": "New York"
},
"phoneNumber": [{
"type": "home",
"number": "111 111-1111"
}, {
"type": "fax",
"number": "222 222-2222"
}]
};
You are calling this.props.fetchContacts(); on componentDidMount, hence in the first render call the state is still empty, the action call and the reducer will pass new props or change the state then you get to the second render call and that's the moment you have the data ready for use.
So you should check for the existing of the data before you try to use it. one way is to just conditionally render it (of course there are better ways to do it, this is just to make a point):
render() {
const { contacts } = this.props;
return (
<div>
<h1>List of Contacts</h1>
<h2>{contacts && contacts.name && contacts.name.first
//still getting error. "this.props.contacts.name" alone works
}</h2>
<h2>{contacts && contacts.address && contacts.address.city}</h2>
</div>
)
}
You are trying to use this.props.contact.name.first is that a typo? shouldnt it be contacts instead of contact?
EDIT:
As a followup for your comment, as a general rule in JavaScript (or any other language for that manner) you should always check the existence reference of an object before you are trying to access it's properties.
As for your use case you can use defaultProps if you must have a value to render or you can even simplify the scheme of your data.
This is much simpler to manage:
export const contacts =
{
"fName": "mkyong",
"lName": "lasty",
"age": 30,
"streetAddress": "88 8nd Street",
"city": "New York",
"homeNumber": "111 111-1111",
"faxNumber": "222 222-2222"
};
Than this:
export const contacts =
{"name": "mkyong",
"age": 30,
"address": {
"streetAddress": "88 8nd Street",
"city": "New York"
},
"phoneNumber": [
{
"type": "home",
"number": "111 111-1111"
},
{
"type": "fax",
"number": "222 222-2222"
}
]
};
Related
This feels like a really stupid question, but my lack of JS knowledge combined with lack of AWS knowledge has me in a tight spot! I'm just trying to get to grips with a basic AWS stack i.e. Lambda/Dynamo/API Gateway for some basic API work.
If I want a simple API endpoint to handle PUT requests e.g. https://my.endpoint.amazonaws.com/users. If I have a DynamoDB table with a composite primary key of userID and timestamp I could use the code snippet below to take the unknown data (attributes that weren't known when setting a schema), but this obviously doesn't work well
const dynamo = new AWS.DynamoDB.DocumentClient();
let requestJSON = JSON.parse(event.body);
await dynamo
.put({
TableName: "myDynamoTable",
Item: {
userID: requestJSON.userID,
timestamp: requestJSON.timestamp,
data: requestJSON.data
}
})
.promise();
I could send a PUT request with the following JSON
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
}
but then address and name get shoved into a single DynamoDB attribute named data. How do I construct the node code to create a new attribute named address and one named name with the corresponding values, if I didn't know these attributes i.e. I want to use JSON in my request like below, but assuming I don't know this and can't use requestJSON.address
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"address": "Elm Street",
"name": "Glen"
}
You can use the spread operator, for example:
const data = {
address: "Elm Street",
name: "Glen",
};
const item = {
userID: "aaaa1111",
timestamp: 1649677057,
...data,
};
console.log("item:", item);
If you insist on the API contract as
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
}
then you can do mapping on the TypeScript level
const request: {userID: string, timestamp: number, data: any} = {
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
};
const ddbObject: any = {
"userID": request.userID,
"timestamp": request.timestamp
};
Object
.keys(request.data)
.forEach(key => ddbObject[key] = request.data[key]);
Representation of ddbObject is
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"address": "Elm Street",
"name": "Glen"
}
How can I get the 'address' array within of request response object below?
{
"title": "MRS.",
"name": "Aluno",
"lastName": "3",
"birthday": "2019-08-31",
"address": [
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
]
}
If I save this object in a state called customer and print console.log(customer.address) it works well and I can see the address informations, but I can't use map or forEach methods like customer.address.forEach, I receive an error :(
You can use methods such as map, reduce, filter, forEach only on Array Not on Object.
the key address has value as an object, To read it you can simply use
console.log(customer.address.addressName) //street x
console.log(customer.address.zipCode) //13901264
If you want to loop through properties
Object.values(customer.address).forEach((value) => {
console.log(value);
})
// OR
Object.keys(customer.address).forEach((key) => {
console.log(customer.address[key]);
})
The property address it not an array, if you need to convert it into an array of one element you can use:
const valueAsArray = [response.address]
Object.keys(out.address).map(key => {
console.log(out.address[key]);
// etc ...
})
Trying get JSON array from json-server using observables and then giving the value to frontend and perform search on the JSON array received through observable
created a service and used HTTP get to connect to server and subscribed to it
created for loop to get value from returned value of subscription
**service.ts**
export class FormdtService {
baseul='http://localhost:3000/objects'//jsonserver url
constructor(private http:HttpClient) { }
getdt():Observable<any>{
return this.http.get(this.baseul)
}
}
**component.ts**
export class FormsComponent implements OnInit {
constructor(public fbu:FormBuilder,private fdts:FormdtService) {}
//creates the reactive form
form=this.fbu.group({
un:'',
id:''
})
// baseul='http://localhost:3000/objects/';
//ngsubmit control of form brings this function
ser(){
this.fdts.getdt().subscribe(dt=>{
console.log("data: "+dt[0])
this.formdt.push(dt)
//console.log("formdt :"+this.formdt[0])
for (let ite in this.formdt){
let ite1=JSON.parse(ite)
// console.log("ite :"+this.formdt[ite]);
//console.log("ite1"+ite1);
this.idlist.push(ite1.person.bioguideid.value)
if(ite1.person.bioguideid.stringify==this.idsearch)
this.objson=ite1
}});
}
idsearch:string
formdt:string[]
idlist:string[]
objson:JSON
ngOnInit() {
}
//this function is attached to button in frontend
ser(){
this.fdts.getdt().subscribe(dt=>
this.formdt.push(dt)//subscribes to service
for (let ite in this.formdt){
let ite1=JSON.parse(ite)
this.idlist.push(ite1.person.bioguideid.value)
if(ite1.person.bioguideid.value==this.idsearch)
this.objson=ite1
})}
**json**
[
{
"caucus": null,
"congress_numbers": [
114,
115,
116
],
"current": true,
"description": "Senior Senator for Tennessee",
"district": null,
"enddate": "2021-01-03",
"extra": {
"address": "455 Dirksen Senate Office Building Washington DC 20510",
"contact_form": "http://www.alexander.senate.gov/public/index.cfm?p=Email",
"fax": "202-228-3398",
"office": "455 Dirksen Senate Office Building",
"rss_url": "http://www.alexander.senate.gov/public/?a=rss.feed"
},
"leadership_title": null,
"party": "Republican",
"person": {
"bioguideid": "A000360",
"birthday": "1940-07-03",
"cspanid": 5,
"firstname": "Lamar",
"gender": "male",
"gender_label": "Male",
"lastname": "Alexander",
"link": "https://www.govtrack.us/congress/members/lamar_alexander/300002",
"middlename": "",
"name": "Sen. Lamar Alexander [R-TN]",
"namemod": "",
"nickname": "",
"osid": "N00009888",
"pvsid": "15691",
"sortname": "Alexander, Lamar (Sen.) [R-TN]",
"twitterid": "SenAlexander",
"youtubeid": "lamaralexander"
},
"phone": "202-224-4944",
"role_type": "senator",
"role_type_label": "Senator",
"senator_class": "class2",
"senator_class_label": "Class 2",
"senator_rank": "senior",
"senator_rank_label": "Senior",
"startdate": "2015-01-06",
"state": "TN",
"title": "Sen.",
"title_long": "Senator",
"website": "https://www.alexander.senate.gov/public"
},//end of single json array object
{
"caucus": null,
"congress_numbers": [
114,
115,
116
],
"current": true,
"description": "Senior Senator for Maine",
"district": null,....same repetition of structure
The ser function should give whole JSON array present in server to formdt[] and then iterate over it and get every object and convert to JSON and push bioguide to id array,search id from input and match with JSON nested value of each object in the array
nothing happens gives error in console :
_this.formdt is undefined at line 37 (this.fdts.getdt().subscribe(dt=>this.formdt.push=dt))
Given error is pretty explicit : this.formdt is undefined.
You've declared preperty type but haven't initialize it.
So replace formdt:string[] with formdt:string[] = []
I am using react to render data from properties in a json that is nested. I don't have a problem rendering the properties that are not nested such as 'name', and 'id', but when it comes to grabbing a nested prop such as place:location{...} etc, it says "TypeError: Cannot read property 'location' of undefined"
My json format looks as follows:
data = [ {
"end_time": "2015-03-28T21:00:00-0700",
"name": "Brkn Intl. Bay Area Season 2!",
"place": {
"name": "MVMNT Studio",
"location": {
"city": "Berkeley",
"country": "United States",
"latitude": 37.85381,
"longitude": -122.27875,
"state": "CA",
"street": "2973 Sacramento St",
"zip": "94702"
},
"id": "459771574082879"
},
"start_time": "2015-03-28T15:00:00-0700" }, ...]
This is my react code:
class ResultBox extends Component {
constructor(props){
super(props);
this.state = {
posts: []
};
}
componentDidMount() {
axios.get('http://localhost:3001/api/events')
.then(res => {
let posts = res.data.map(obj => obj);
this.setState({posts});
console.log(posts);
});
}
render() {
return (
this.state.posts.map(function(events){
return <div className='result_box'>
<p>{events.name}</p>
<p>{events.place.location.city}</p> <----- This give me error!!!
</div>
})
);
}
}
Any help would be appreciated!!!!
It looks like not all events have property place defined.
You can either warn about it on every component or just ignore and prevent undefined values to be rendered:
this.state.posts.map(events =>
<div key={events.id} className='result_box'>
<p>{events.name}</p>
{events.place && <p>{events.place.location.city}</p>}
</div>
)
Lodash's get method also can help you with this:
<p>{get(events, 'place.location.city', '')}</p>
I am reading the below json value from a module.js
.controller('home.person',['$scope','$filter','personResource',function($scope,$filter,personResource) {
$scope.searchPerson = function() {
var params = $scope.search || {};
params.skip=0;
params.take =10;
$scope.personDetails =
{
"apiversion": "0.1",
"code": 200,
"status": "OK",
"mydata": {
"myrecords": [
{
"models": [
{
"name": "Selva",
"dob": "10/10/1981"
}
],
"Address1": "ABC Street",
"Address2": "Apt 123",
"City": "NewCity1",
"State": "Georgia"
},
{
"models": [
{
"name": "Kumar",
"dob": "10/10/1982"
}
],
"Address1": "BCD Street",
"Address2": "Apt 345",
"City": "NewCity2",
"State": "Ohio",
"Country":"USA"
},
{
"models": [
{
"name": "Pranav",
"dob": "10/10/1983"
}
],
"Address1": "EFG Street",
"Address2": "Apt 678",
"City": "NewCity3",
"State": "NewYork",
"Country":"USA",
"Zipcode" :"123456"
}
]
}
}
}
}])
Now i am able to statically build the UX. But my each record set's key value pair count is different. So i want to build my html dynamically as per the current record set's count.Country & Zipcode is not exist in all records so i need to build dynamically the build and populate the html output.Most of the time, my json output is dynamic. Instead of persondetails, i may get the json output of a product details instead of PersonDetails.
<div ng-show="personDetails.mydata.myrecords.length > 0" ng-repeat="recordSingle in personDetails.mydata.myrecords">
<div >
<span >Address1: {{recordSingle.Address1}}</span>
<span >Address2: {{recordSingle.Address2}}</span>
<span>City: {{recordSingle.City}}</span>
<span>State: {{recordSingle.State}}</span>
<span>Country: {{recordSingle.Country}}</span>
<span>Zipcode: {{recordSingle.Zipcode}}</span>
</div>
</div>
One way is to use ng-if statement, for the optional span elements:
<span ng-if="recordSingle.Address1">Address1: {{recordSingle.Address1}}</span>
[Update #1: updated based on revised comments to question]
[Update #2: fixed typos in function and included plunkr]
I now understand that you want to dynamically build the display objects based on properties from the JSON object. In this case, I would iterate through the properties of the object. I would use a function to produce this array of properties for each object so that you can filter out any prototype chains. I would also remove out any unwanted propoerties, such as the internal $$hashKey and perhaps the array objects e.g.
In your controller:
$scope.getPropertyNames = getPropertyNames;
function getPropertyNames(obj) {
var props = [];
for (var key in obj) {
if (obj.hasOwnProperty(key) && !angular.isArray(obj[key]) && key !== '$$hashKey') {
props.push(key);
}
}
return props;
}
Then in your HTML view:
<div ng-repeat="record in personDetails.mydata.myrecords">
<div ng-repeat="prop in getPropertyNames(record)">
<span ng-bind="prop"></span>: <span ng-bind="record[prop]"></span>
</div>
</div>
This works for me... see this plunker. It is displaying each of the properties of the object in the array dynamically (you could have any property in the object). Is this not what you are trying to achieve?