I ran a api and get the json object of object. Below is the screenshot of that object. In react native, I am getting this data in component from redux with the key "data".
When I try to fetch city name in mapStateToProps component, I am getting this error
TypeError: Cannot read property 'name' of undefined
Blockquote
my mapStateToProps is below.
const mapStateToProp = ({data}) => {
//console.log(data);
return {
city: data.data.city.name
}
}
I am getting complete data to city but unable to access its name property Why?
Since you're getting the data from a fetch request the city property probably doesn't exist before the request. Try preventing the error by checking if the city exists when you set the value in mapStateToProps
const mapStateToProp = ({data}) => {
//console.log(data);
return {
city: data.data.city ? data.data.city.name : null
}
}
Keep in mind that it is also a good practice to not have deeply nested data in your store.
Related
I have created a Home.js and included inside App.js of my react app.I want to fetch json data but I am getting the following error-
My Code- https://stackblitz.com/edit/react-kwaooy?file=src/App.js
For initial load your this.state.lists.regionData will be undefined and you are accessing the undefined value that might be the issue for crashing the application.
Change your state value like below,
this.state = {
lists: {
regionData: [],
activeCases: '',
activeCasesNew: '',
deaths: ''
}
};
You need to check what you are actually storing in the list state from the response. What I see is that you are storing response.data but you might actually want to store regionData from the response. This will allow map to iterate over the regionData values and not show this error.
I'm using knex with MYSQL. I have a function that I called to show the data to the user, Also I'm using a view table which has 5 right join on it and I think it will take some time to return values from the table plus I added the WHERE condition on my knex and it looks like this :
var showClass = (teacherId , ClassId){
return new Promise((resolve , reject)=>{
knex.select().from('v_cardex_details').where({teacherId }).andWhere({id : ClassId}).then(classes =>{
resolve(classes)
}).catch(err=>{
console.error(`Show Teacher class Error: ${err}`)
reject (err)
})
})
}
and I call this general function to response some request something like this
exports.EditClass = (req,res)=>{
knex('Table').update({//Some update stuff here}).then(()=>{
showClass(req.user.id, req.params.id).then(data=>{
return res.status(200).json({data , message:''})
})
}).catch()
}
With the same input, this function after updating returns value and some times it returns an empty string, especially when it's on the hosting server most of the time it returns nothing but { message : '' }
Try to create simplified code by removing all the unnecessary wrappers and you might find where your problem is. AFAIK there is no way that that your {data , message:''} would create an object containing just {message: ''} without any additional attributes.
> var data = []
undefined
> {data, foo:1}
{ data: [], foo: 1 }
> data = undefined
undefined
> {data, foo:1}
{ data: undefined, foo: 1 }
> {data1, foo:1}
ReferenceError: data1 is not defined
The problem you are experiencing does not exist in from the code you have shared (though there are syntax errors and other problems).
EDIT:
res.json() uses JSON.stringify() to convert js object to JSON strings. So if value of data in your code is undefined instead of and array, that could explain the behavior you are experiencing:
λ node
> JSON.stringify({ test: undefined })
'{}'
As you can see JSON.stringify() omits the attributes with value undefined from the output JSON string.
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 2 years ago.
I am attempting to create a weather app using the Openweather API. I am able to retrieve the JSON object successfully, but I am having trouble iterating through the object, I would like to access the weather details for specific dates and times but I just cannot for the life of me wrap my head around the concept. There were times where I was able to access the name of the JSON object, but when I attempt to access a specific weather detail from a specific date and time, I am met with errors constantly. Some of the information is so deeply nested that I am unsure exactly how to retrieve the information
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=${zip}&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
console.log(json.list);
});
}, [apiSearch]);
If I simply try to add an index to the end of json.list:
console.log(json.list[1]);
I am sometimes met with errors such as Cannot convert undefined or null to object or something along those lines, I would like to know the best way to access the object array below and all of its information, thank you!
I've tried multiple approaches including Object.keys, mapping, etc. but I always get hit with an object is null error or something of the sorts. I would like to iterate through the 40 arrays and lets say access the temperature, every attempt to do so has led me to failure. Any help would be greatly appreciated, thank you!
Hope this will help you.
fetch(`https://api.openweathermap.org/data/2.5/forecast?zip=99501&units=imperial&appid=5672e526c1cbc8d71aed230e5e151426`)
.then(response => response.json())
.then(json => {
const forcasetList = json.list;
forcasetList.forEach(f => {
console.log(f.main.temp)
})
});
There can be several issues here:
Fetch and response status
Since you are using fetch the returned response may not always be a valid response, you should first check that you have an HTTP 200 status response e.g.:
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(...)
Impartial / Invalid data
I am not familiar with the openweathermap API but from what i can see in the API the forecast list should always have complete non null objects.
But you could add some validation or guards by either e.g.:
Using a JSON schema validation like AVJ
Or having a parse method that checks for the list and returns non null elements
fetch(url).then(
response => {
if (response.status !== 200) {
throw new Error(`Expected status 200 ok got status: ${response.status}`)
}
return response.json()
}
).then(
forecast => {
// here you could validate using something like AVJ to
// check that the json response is valid
if (!valid(forecast)) {
throw new Error('Invalid forecast data')
}
// Some custom filtering and validation example
const list = forecast.list || []
return list.filter(
item => {
// filter out null objects
if (!item) {
return false
}
// other validations.
...
// validate the date is within your range
if (item.dt ...) {
return false
}
// valid item
return true
}
)
.map (
// extract the weather part
item => item.weather
)
}
).then(
weatherItems => {
// work with weather items here
}
)
I am new to Angular, and I'm working on a project with Ionic Angular. My goal is to use the httpClient and send get request to a Country api that will send me back a JSON of all the countries. The way I used to store the data is to create an interface matching the data type that I am receiving from and then subscribe to that observable and store the data into the array of the data type that I defined.
But for the countries, the only thing I need is the name, is it possible to store the name of each countries into an array without defining the structure of the receiving JSON object, because it's very long and complex.
This is the code that I am trying to do:
Getting the countries as Observable. in the Country.Service file
getCountry(): Observable<any>{
return this.http.get<any>(this.url2);
}
Declaring variable and store the data of countries:
public countries: any;
storeCountry(){
this.countryService.getCountry().subscribe(
data => {
this.countries = data;
}
);
This is what I'm trying to do, but I was not able to get the data into the countries variable to access it as array, when I console log the countries it is showing as undefined.
What would be the best approach to what I'm trying to achieve? I would appreciate any help,
I assume the data you receive from the backend is of the structure
countries = [
{ 'name': 'USA', 'id': '1', ... },
{ 'name': 'UK', 'id': '2', ... },
...
]
In that case you could remove the <any> from the GET request and use map() method to obtain only the country names as an array. Try the following
Service
import { pipe } from 'rxjs';
import { map } from 'rxjs/operators';
getCountry(): Observable<any>{
return this.http.get(this.url2).pipe(map(countries => countries.map(country => country.name);
}
Explanation
If you're new to Rxjs as well, then you might be confused why there are two map functions.
The pipe(map()) part belongs to Rxjs.
pipe() function can be used to modify and control the data flow using various Rxjs operators.
We use only one operator map() which projects a custom function on the source observable (JSON returned from the API) and returns the resulting value as an observable.
We use the map() function in countries.map() to provide our custom projection function. It creates a new array based on our callback to use only the name property of the source object array.
Then you could subscribe to it in the component
storeCountry(){
this.countryService.getCountry().subscribe(
countries => {
this.countries = countries; // this.countries = ['USA', 'UK', ...]
},
error => {
// handle error
}
);
}
I'm following an angular-nodeJS tutorial and I'm trying to recover data from a MySQL database. Here's my db creation script:
CREATE DATABASE ng_games_db;
USE ng_games_db;
CREATE TABLE games (
id INT (11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(180),
description TEXT(255),
image VARCHAR(200),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
My db connection works cause I can add entries to my only table from my app. However, when I try to get the data with this method:
public async list (req : Request, res : Response) : Promise<void> {
const games = await pool.query('SELECT * FROM games');
res.json(games);
}
I get the following error:
(node:5828) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Query'
| property '_timer' -> object with constructor 'Timer'
--- property '_object' closes the circle
at JSON.stringify (<anonymous>)
at stringify (C:\Users\Dave\Documents\angular-mysql-crud\server\node_modules\express\lib\response.js:1123:12)
at ServerResponse.json (C:\Users\Dave\Documents\angular-mysql-crud\server\node_modules\express\lib\response.js:260:14)
at C:\Users\Dave\Documents\angular-mysql-crud\server\build\controllers\gamesController.js:23:17
at Generator.next (<anonymous>)
at fulfilled (C:\Users\Dave\Documents\angular-mysql-crud\server\build\controllers\gamesController.js:5:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
I've been searching the internet for a while trying to fix it but I've had no luck so far.
EDIT: Here is a library I've used before that might work for your situation:
https://www.npmjs.com/package/flatted
JSON.stringify doesn't handle circular references very well, like other serializers might pass a reference, stringify() crashes. You can try this, which will remove circular references:
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(games, getCircularReplacer());
// {"otherData":123}
Here is a link where the code snippet came from:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
In the footnotes of the link above, there is also mention of cycle.js which handles circular references.
https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
Ultimately, you need to find a JSON serializer/ deserializer that is capable of decoding these references.
FOR PEOPLE STILL HAVING ISSUES:
For those who still have an issue with this after adding the flatted package, you need to add this line in after you create your database pool: pool.query = util.promisify(pool.query); - source: https://mhagemann.medium.com/create-a-mysql-database-middleware-with-node-js-8-and-async-await-6984a09d49f4
If you are using typescript it will complain but simply add // #ts-ignore above it and you should be fine.
You will now be able to make mysql select queries using try/catch and async/await!!
This command works fine for your problem:
pool.query ('SELECT * FROM games', function (err, rows) {res.send (rows);});