Unable to read properties of a property containing the object - javascript

I'm having an issue trying to access the properties of an object, which has a reference property of another object. In other words, an object contained in other object.
After fetching the data from API calls like this one for example:https://api.apixu.com/v1/current.json?key=2352219608ed457fb3a12903193008&q=Helsinki my code get the response's data and set the hook's value: capitalWeather.
Anyways, the object has two attributes: location and current, which are also object type. Everytime I try to access any value from a reference, like accessing value of capitalWeather.location.region what I get is=
Uncaught TypeError: Cannot read property 'region' of undefined
As expected, It also applies for any of the other attributes: name,country,lat,lon,tz_id,etc....
I don't understand why I'm getting a typeError, considering both are object types.
This is the code snippet where the error takes place:
const Displayer = ({ country }) => {
const [capitalWeather,setWeather]=useState([]);
useEffect(() => {
axios.get(`https://api.apixu.com/v1/current.json?key=2352219608ed457fb3a12903193008&q=${country.capital}`)
.then(response => {
console.log('Promise fullfiled, succesfully fetched data');
setWeather(response.data);
})
}, [country.capital]);
console.log(capitalWeather.location.region);
return (<div className='displayer'>
<h2>{country.name}</h2>
<p>Capital {country.capital}</p>
<p>Population {country.population}</p>
<h4>Languages</h4>
<ul>
{country.languages.map(lang => <li key={lang.name}>{lang.name}</li>)}
</ul>
<img src={country.flag} alt='this is the country flag'></img>
{/*<Weather weather={capitalWeather}/>*/}
</div>)
}

capitalWeather is initialized as an array in this code.
const [capitalWeather,setWeather]=useState([]);
capitalWeather.location.region for sure will throw an error because it does not have a property location.

Related

TypeError: Cannot read properties of undefined (reading 'map') , Unable to get data from api

const handleData = (e) => {
e.preventDefault()
var config = {
method: 'get',
maxBodyLength: Infinity,
url : ''
headers : {}
};
axios(config)
.then((response) => {
setIsData(JSON.stringify(response.data))
console.log(response);
})
.catch((error)=> {
console.log(error);
});
}
<p onClick={(e) => handleData(e)}>
{isData?.map(product => {
return <p key={sectionTypes.NEWLY_JOINED}>{product}</p>
})}
</p>
I've been trying to display id's to sort and display them according to their respective section ids, but this error keeps on coming on the page.
the console.log says "GET_TODAY_PROFILE_FAILURE"
I don't know what I am doing wrong. Is it something in the map function I am doing wrong or am I doing something wrong while getting the data?
You are stringify your response in state and then directly using map function on the state for that reason this error occurs.
you need to parse your data and then apply map function on it.
possible solutions:
don't stringify the response so you can directly use it as a array form.
parse your state before using them with JSON.parse(isData) in some variable and then add map function to this array variable.

Array list is shown, array length is 0 and elements are undefined in react

So, basically i have two api calls in two different functions that are called from a single component page. The await function is applied to each of them because each of the response provided from the first api is used as params to the second api. for the first api call, inside the function, the response is pushed to the array named all_countries.
const apiCall = getCountry(req)
.then((response) => {
all_countries.push(...response);
dispatch(actionSuccess(NICE_ONE, response));
})
.catch((error) => {
dispatch(actionFailure(NICE_ONE, error));
});
each of the array objects inside all_countries is to be mapped and value(i.e country code present inside each object from all_countries) is used to call another api to get the response but my problem is upon console logging the all_countries from the second function, it shows the symbol of empty array. upon opening the array, it lists all the countries. when i console log the length of the array, it shows 0 and upon console logging the elements like all_countries[0], it shows undefined. Why is this happening? Could someone help me out please?
This gets shown on console
Upon expanding, this is shown:
enter image description here
So, i found that on adding all_countries.push, intellij shows me a warning, response is not an array type but rather AllCountryRes type.
AllRelaysRes type is defined as:
export type AllRelaysRes = {
logo: string;
ipv4: string;
ipv6: string;
port: string;
location: {
id: number;
ip: string
};
};
and the getCountry function is like this:
export const getCountry = (url: string): Promise<AllRelaysRes> => {
ExternalApi.setBaseUrl(url);
return ExternalApi.apiCall<AllRelaysRes>({
method: "GET",
url: "something",
});
};
The response from the api is an array of objects. I am just a beginner with typescript and trying out stuffs. My question is how do i make the response type as an array of object AllRelayRes? Doesnot return ExternalApi.apiCall angular brackets AllRelayRes mean that the response expected is an array of AllRelayRes since, AllRelayRes is kept inside the angular brackets? How do i fix this? Is this the real problem why i get the array length 0?
I believe you're dealing with a collection of objects of type AllRelayRes, not an array. It shows as [] in the console, but that represents a collection.
If you want to use it as an array, specify the type in your function <AllRelaysRes[]>
export const getCountry = (url: string): Promise<AllRelaysRes[]> => {
ExternalApi.setBaseUrl(url);
return ExternalApi.apiCall<AllRelaysRes[]>({
method: "GET",
url: "something",
});
};
Then you should be able to manipulate the data in an array format
If you want to keep it as a collection, you can probably iterate through them with
let x, key, obj
for(x in AllRelayRes) {
key = x; // 0, 1, 2 .. the index
obj = AllRelayRex[x] // the object
// country_name = AllRelayRex[x].country_name, etc
}

add a property to a created object (Firebase Functions)

I'm hooking to the creation of objects on a specific collection (orders)
I need to add a new property to the object before it's saved, not returning anything, to no avail.
I have looked at the documentation at https://firebase.google.com/docs/reference/functions/functions.firestore.DocumentBuilder#writing_data
but it's for onUpdate so it doesn't work as i intend it.
exports.createOrder = firestore.document('orders/{orderId}').onCreate((snap, context) => {
const newOrder = snap.data()
console.log('triggered', newOrder)
const orderId = randomize('A0', 10)
console.log({ orderId })
return newOrder.ref.set({ orderId }, { merge: true })
//newOrder.ref.set is undefined
return newOrder.set({ orderId }, { merge: true })
//newOrder.set is undefined
})
snap.data() returns a raw JavaScript object whose properties contain the values of the fields in the document. It does not contain a property called ref (unless you had a document field also called ref).
If you need to write back to the document that changed, use the DocumentReference type object provided in snap.ref. See also the API documentation for the DocumentSnapshot type object passed to the function.
snap.ref.set(...)

Why does my add like method return "cannot read property of undefined"?

I wrote a method to handle adding a "like" on click. It's supposed to toggle isLiked to the opposite of the previous state and increment likes count by 1.
I think the error might be due to conflicting states but I'm not sure how to verify this.
addLike = postId => {
this.setState({
posts: this.state.posts.map(post => {
if (post.id === postId) {
return {
...post,
likes: post.likes + 1,
isLiked: !post.isLiked
};
}
return {
post
};
})
});
};
I was expecting like to increment by 1 and isLiked to be set to true. However, on click I'm getting an error that it "cannot read property of undefined".
You can code defensively against potentially missing properties:
if (post && post.id === postId) { // is it possible your posts array has `undefined` or `null` entry in it?
return {
...post,
likes: post.likes + 1;
isLiked: !post.isLiked
};
...
And elsewhere, where trying to access a property on a null or undefined object could throw that exception. For example, is state.posts properly populate or at least initialized to an empty array []? If not, this.state.posts.map could also throw the same error.
Furthermore, use React DevTools extension to inspect your state and check the values.
If your setState should rely on the previous state, then better go with the syntax with updater function. Something like
this.setState(({posts, ...restOfTheState}) =>
({
posts: posts.map( // mapping logic here
...restOfTheState,
});
BTW, state.posts was initialized, right?

vue computed property not able to get data

I am currently experiencing an issue where the computed() property is not able to get data. Although data was already initiated in created() property. Am I doing it wrong? Please advise how I can fix this issue.
const randomPlayers = {
template:
`
<input type="text" v-model="search_player">
<div v-for="player in modPlayers" v-if="list_of_random_players!=null">
<p>{{player.firstname}}</p>
<p>{{player.lastname}}</p>
<div>
`,
props: ['data'],
data (){
return{
list_of_random_players: null,
search_player: null
}
},
created(){
this.get_random_players()
},
computed: {
modPlayers(){
return this.list_of_random_players.filter( person => {
return !this.search_player ||
( person.firstname.toLowerCase().indexOf(this.search_player.toLowerCase()) > -1 || person.lastname.toLowerCase().indexOf(this.search_player.toLowerCase()) > -1)
})
}
},
methods: {
get_random_players: function(){
$.post(
url:'random_url'
data: {
players: data
}
).done((success)=>{
this.list_of_random_players: JSON.parse(success)
})fail((err)=>{
console.log(err)
})
}
}
}
I get the following two errors:
(1) TypeError: Cannot read property 'filter' of null
(2) TypeError: this.list_of_random_players.filter is not a function
From Vue: "When a Vue instance is created, it adds all the properties found in its data object to Vue’s reactivity system. When the values of those properties change, the view will “react”, updating to match the new values."
So data is a function that returns an object but as mentioned by #Sovalina you are not returning it so you cannot access its properties. You need to add return and change null to []:
data() {
return {
list_of_random_players: [],
search_player: []
}
},
or you can do without return and like a regular object:
data: {
list_of_random_players: [],
search_player: []
}
When your Vue component is used multiple times, it is better to use it like a function(first case).
"When defining a component, data must be declared as a function that returns the initial data object. Why? Because there will be many instances created using the same definition. If we still use a plain object for data, that same object will be shared by reference across all instance created! By providing a data function, every time a new instance is created we can call it to return a fresh copy of the initial data."
Reference:link
It might be just a typo but you need to add : to methods as well.

Categories

Resources