exact array using ES 6 from an array of object - javascript

I'm working with Angular 5 http Client to fetch data from an API. This is my subscribe part
vehicles: Vehicle[];
getVehicleList() {
this.vehicleService.getVehicleData()
.subscribe(data => {
this.vehicles = data
console.log(JSON.stringify(data));}
)
}
Vehicle interface
export interface Vehicle {
type: string;
}
I'm getting an JSON look like this
{
"data": [
{
"type": "bus"
},
{
"type": "truck"
},
{
"type": "car"
}
],
"_metadata": null
}
I want to get only array from above using map function. Could someone help me with this?

I'm not sure about what you are asking here, but as Khauri pointed out, you can get the data array by using data.data.
If you want to use map on top of it, it would look like this :
data.data.map(element => console.log(element.type))
This would pritnt
bus
truck
car
[EDIT] If you just want to get the array, you should just use data.data
Assuming you are using typescript, you need to add to your Vehicule interface a data field, which is an array.

in my opinion the solution of the comments before should work.
Please make sure, that you changed your code to the following:
vehicles: Vehicle[];
getVehicleList() {
this.vehicleService.getVehicleData()
.subscribe(data => {
this.vehicles = data.data;
})
}

Related

Why can I access nested objects before setting my state but not after?

I'm creating a Pokedex app using React as a practice exercise as I've just been learning it, and I'm hitting a bit of a weird snag. So the basic set up so far is I have a PokemonList component that is basically the parent component for a bunch of individual PokemonPreview components. It's in creating these PokemonPreview components and grabbing information from the pokeapi that I'm having some issues. Here's my example code from my PokemonPreview component (just the relevant bits):
const [pokemonInfo, setPokemonInfo] = useState({})
const name = props.pokemon.name.charAt(0).toUpperCase() + props.pokemon.name.slice(1)
const url = props.pokemon.url
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
console.log(data.types[0].type.name)
setPokemonInfo(data)
})
}, [])
return (
<div style={{backgroundColor: '#F06430'}} className="pokemon-preview">
<h3>{name}</h3>
<h5>#{pokemonInfo.id}</h5>
<h5>{pokemonInfo.types[0].type.name}</h5>
</div>
)
The name and url are both passed as props from the PokemonList component, and the url is then used to pull the full details for the pokemon from the pokeapi (ex: https://pokeapi.co/api/v2/pokemon/6). Basically, I'm doing the fetch request to get the data for the pokemon, and saving that whole object as my state, so I can pull whatever info from that object in state as I need it. The weird thing that I'm seeing is that I can't pull some info from my state object. Here is an example of the JSON that is stored in my state object:
{
"abilities": [
{
"ability": {
"name": "blaze",
"url": "https://pokeapi.co/api/v2/ability/66/"
},
"is_hidden": false,
"slot": 1
},
{
"ability": {
"name": "solar-power",
"url": "https://pokeapi.co/api/v2/ability/94/"
},
"is_hidden": true,
"slot": 3
}
],
"base_experience": 240,
"types": [
{
"slot": 1,
"type": {
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/"
}
},
{
"slot": 2,
"type": {
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/"
}
}
],
"weight": 905
}
What I'm trying to access are the entries in the types array. As you can see in the console log in my example code, I'm able to grab the first entry in the types array from the request data, but if I try to get that same info from my state using a console log or in the component's return, I get an error: TypeError: Cannot read property '0' of undefined. The pokemonInfo.id part in the return works but not the more nested types part. I really can't figure out why I'm able to get this info before setting it to my state, but not after. Does anyone know why this is happening? Should I just create separate state variables for each piece of the pokemon's information, instead of storing it in one big object to pull out later?
Thanks!
Ok so the reason for the error is you're trying to render the info before it's loaded, since the pokemon info is fetched from an API. You have to accommodate for that. Here's a basic technique:
// Set it to null initially, since it's not defined at all
const [pokemonInfo, setPokemonInfo] = useState(null);
...
// Check if the pokemon info is null before trying to access nested data
return (
<div style={{backgroundColor: '#F06430'}} className="pokemon-preview">
<h3>{name}</h3>
{
pokemonInfo === null ?
<h5>Loading pokemon data...</h5> :
<>
<h5>#{pokemonInfo.id}</h5>
<h5>{pokemonInfo.types[0].type.name}</h5>
</>
}
</div>
)
And of course make sure the object paths are all correct

passing in json variable into sendgrid's dynamic_template_data

I'm having some trouble passing into a variable that holds a json object into sendgrid's dynamic_template_data. My setup looks like this:
const send = async (address, mentions) => {
console.log('mentions json obj', mentions)
let name = "john"
try {
let config = {
headers: {
Authorization: `Bearer ${process.env.sendgridKey}`,
}
}
let data = {
personalizations: [
{
to: [
{
email: `${address}`,
},
],
dynamic_template_data: {
name: name,
allMentions: mentions
}
}
],
from: {
email: "email#email.com",
name: "Mentionscrawler Team"
},
template_id: process.env.template_id,
}
await axios.post("https://api.sendgrid.com/v3/mail/send", data, config)
} catch (error) {
console.error(error, 'failing here>>>>>>>')
}
}
when I console.log mentions, which is json, and paste the code I get from the terminal directly into the allMentions key, it works. but when I just pass in mentions itself, nothing shows up on the sent email. I've been very confused the last few hours why this is happening. Any advice appreciated.
edit: i should also note that allmentions is an object with keys that hold arrays. So I'm looking to iterate over those arrays. Again, this totally all works if I just paste in directly what mentions is, but passing in mentions is giving me an issue.
Thank you very much,
just realized what was wrong. sendgrid's template requires a json object, so I assumed that I needed to use json.stringify on my mentions obj. Turns out I didn't need to do that, as long as all values are in string format.

Store array from firebase database

l am trying to build a project using Angular and angularfire. My project is about drawing polygons using leaflet map, then pushing coordinates of a polygon to a database. I have successfully pushed an array to the database, but I have a problem to retrieve coordinates from database.
Database Structure :
{
"Locations" : {
"-M0M9kqEbE0FVMzIZAg0" : {
"text" : [ [ {
"lat" : 35.97800618085566,
"lng" : 42.03369140625001
}, {
"lat" : 33.88865750124075,
"lng" : 41.46240234375001
} ] ]
}
}
}
I am trying to store array above in class ts not in html.
My code :
export class WeatherNowComponent {
itemsRef: AngularFireList<any>;
items: Observable<any[]>;
coords :any
constructor(private db: AngularFireDatabase) {
this.itemsRef = this.db.list('Locations')
// Use snapshotChanges().map() to store the key
this.items = this.itemsRef.snapshotChanges().pipe(
map(changes =>
changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
)
);
this.db.list('Locations').snapshotChanges().subscribe((markers: any) => {
console.log(markers)
markers.forEach(singlemarker => {
console.log(singlemarker)
// ADD COORDS to MAP POLYGON
var polygon = L.polygon([singlemarker.text.lat,singlemarker.text.lng], {color: 'red'}).addTo(this.map);
});
});
console.log(this.items)
}
}
So I have only key array in console log without rest of array objects.
If you calling a spread operator on purpose because it is an array try assigning it to a property value in the object literal definition.
{ key: c.payload.key, values: ...c.payload.val() }
Edit: Based on your comment I would still say still just assign the array of coordinates (lat/lng property pairs objects) to the values property to iterate over later. I assume the .val() method must return the array of those values. Otherwise please post what .val() returns.
Also, I noticed something else you should check.
The observable is calling the RxJs pipe() method to map but I didn't notice a subscribe() anywhere. While .pipe() lets you map and filter the callback needs a subscribe.
Edit #2: Based on your second comment below. What you are asking for is still unclear to me. So I will give two more possible answers based on the comment: "okay , my question is how i can get array directly ?"
// Possibility #1
// Simplest is to store off the returned data into the coords variable for later processing.
// You can then get the array directly at any later point just by accessing the coords
this.db.list('Locations').snapshotChanges().subscribe((markers: any) => {
coords = markers;
});
// Possibility #2
// Since the data structure you are using works like a dictionary data structure
// Define some structures to store off the data and get at the array data directly later
// Define this somewhere outside your class
interface ICoordinate {
lat: string;
lng: string;
}
// Initialize coordinate dictionary
let coordinates: { [key: string] : ICoordinate[]; } = {};
// Retrieve locations and store off coordinates to get at the array data directly
this.db.list('Locations')
.snapshotChanges()
.subscribe((markers: any) => {
coordinates[markers.key] = ICoordinate[];
markers.forEach(singlemarker => {
coordinates[markers.key].push({ lat: singlemarker.text.lat, lng: singlemarker.text.lng });
});
});
Edit #3: Oh yes, I see. The array needed to be initialized before adding to it.
Updated code. Also, as an additional help to you on future questions it is very helpful if you have a snippet. S.O. question to refer to: I've been told to create a "runnable" example with "Stack Snippets", how do I do that?
Hopefully that helps.
Happy coding!

Filtering away javascript objects into an array when using fetch

I have a react application, where I use the axios library, to get some values, and set them into an array of javascript objects in my state
componentDidMount(){
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => this.setState({animals: res.data}))
}
Now I want to check if the objects, contains an Owner object, inside it, and filter out does that does,
First, I tried making a const, and then using the filter, to check if they contain the objects, and then set the state, but I can't save my values in a local variable
componentDidMount(){
const animals= [];
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => animals=res.data)
console.log(animals) // logs empty array
console.log('mounted')
}
how can I make it so, that I can only get the animals that do NOT, have an owner object inside it?
Your animal array is empty in your second example because axios.get is asynchronous, what is in your then will be executed once the data is fetch, but the function will keep on going in the meantime.
To filter out your array, simply use filter right after fetching your data :
componentDidMount(){
axios.get('http://localhost:8080/zoo/api/animals')
.then(res => this.setState({animals: res.data.filter(animal => !animal.owner)}))
}
This function will filter out every animal object that does not have an owner property.
Working example :
const animals = [
{
name: 'Simba',
owner: {
some: 'stuff'
}
},
{
name: 1
}, ,
{
name: 2
}, ,
{
name: 3,
owner: {
some: 'stuff'
}
},
{
name: 'Bambi'
//status: 'dead'
}
]
console.log(animals.filter(animal => animal.owner))
EDIT: the answer was changed so that it only filters animals, that does not have an owner

GraphQL query returns error "Cannot return null for non-nullable field"

I have a basic GraphQL query setup as follows:
Query.js:
const Query = {
dogs(parent, args, ctx, info) {
return [{ name: 'Snickers' }, { name: 'Sunny' }];
},
};
module.exports = Query;
schema.graphql:
type Dog {
name: String!
}
type Query {
dogs: [Dog]!
}
I created a function createServer() for starting the server as follows:
const { GraphQLServer } = require('graphql-yoga');
const Mutation = require('./resolvers/Mutation');
const Query = require('./resolvers/Query');
const db = require('./db');
function createServer() {
return new GraphQLServer({
typeDefs: 'src/schema.graphql',
resolvers: {
Mutation,
Query,
},
resolverValidationOptions: {
requireResolversForResolveType: false,
},
context: req => ({ ...req, db }),
});
}
module.exports = createServer;
I then tried querying dogs as follows:
query {
dogs {
name
}
}
But instead of getting the names from the array of dogs, I got the following error instead:
{
"data": null,
"errors": [
{
"message": "Cannot return null for non-nullable field Query.dogs.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"dogs"
]
}
]
}
What seems to be causing this error?
This problem comes from AWS requiring certain standard values in the dynamoDB table, such as createdAt and updatedAd, just add these fields manually with a timestamp in dynamo db for further testing. A mutation always needs to be requested via id, this somehow was not clear to me when my schema was created by amplify codegen...
The above code works as you can see in codesandbox: https://codesandbox.io/s/olzj9vvpk5
But when I convert Query to something like {} it returns the same error so please check your paths and console.log Query to validate the path. Your export looks correct but you might have forgotten to save the file as I can see from the course starter files Query is an {}. Please double check.
Also if this code is in a public git repo please share the link.
I know this question has been answered, but for me the only thing that fixed this issue was to also pass the info argument.
In my case, I create a new Query.js file at the src folder but I import Query with Query = require('./resolvers/Query') and coding there. So, try to check the path, I think the problem is there.

Categories

Resources