I need to map enum values to 1 variable and then call the variable and check if that enum was present or not.
render() {
const {
id,
name,
features} = this.props;
}
Features would be the variable that needs to be mapped according to which enums are coming in. I would get something similar from the API:
{"id":"111", "name":"jack", "features":["MOUNTAIN", "HILL"]}
So there would be a total of 4 different features : MOUNTAIN, HILL, LAKE, FISH.
Then when needed I can check:
if(features.mountain)
//do stuff
If you like to check if a given property from your enum (for example "MOUNTAIN") is included in the features array returned from the api you can use the Array.prototype.includes() method:
if(featuresArrayfromApi.includes('MOUNTAIN'){
//do stuff
}
If you would like to check if the features returned from the api include one or more of the properties in your features enum you can combine includes with Array.prototype.some().
For example, in Typescript you would write it like this:
enum Features { MOUNTAIN, HILL, LAKE, FISH }
if(Object.keys(Features)
.some(feature => featuresFromApi.includes(feature))){
// do stuff
}
Edit
The features key from the api data should be mapped like any other key(id, name) - just instead of holding 1 value it holds an array. Then you can use the validations suggested above in an if clause. For example:
const data = [
{"id":"111", "name":"jack", "features":["MOUNTAIN", "HILL"]},
{"id":"222", "name":"john", "features":["FISH", "HILL", "LAKE"]}
{"id":"333", "name":"joe", "features":["LAKE", "HILL", "FISH"]}
]
data.map(record =>{
console.log(record.id);
console.log(record.name);
if (record.features.includes('MOUNTAIN'){
// do stuff
}
})
Also, bear in mind that enum is a Typescript symbol which isn't available in Javascript, so in case you are not using Typescript you can just declare it like this and it would work the same:
const Features = {
MOUNTAIN: "MOUNTAIN",
HILL: "HILL",
LAKE, "LAKE",
FISH: "FISH"
}
Related
I want to check if a value exists in an array of objects.
My array looks something like this:
[
0: {
id: 'unique_obj_id',
item: {
id: 'unique_item_id',
...
},
...
},
1: {...}
]
The objects in the array can be one of many interface types (depending on my api call, here: resource strings represent these interfaces, which are defined somewhere else). But one array will always consist of the same interface types for a given data request.
I'm trying to write a reusable function to check whether given_id exists for any object in the array for obj.item.id.
So far I've managed to write the correct logic but typescript throws some exceptions that I can't seem to figure out. shopApprovalData is a collection of interfaces each following the above object structure accessible by the indices of resource.
export type ApprovalResource = 'str1' | 'str2' | 'str3' | 'str4' | 'str5';
export const checkApprovalItem = (given_id: string, resource: ApprovalResource) => {
const shopApprovalData = useShopApprovals();
if (shopApprovalData && shopApprovalData[resource]) {
const resourceApprovalData = shopApprovalData[resource];
if (resourceApprovalData.find(e => e.item.id === id)) {
return true;
}
}
return false;
}
Typescript shows me that shopApprovalData and itemApprovalData is possibly undefined and that the expression find() is not callable since signatures of members of the union type are not compatible with each other. (Apparently, some removes the error, why?)
What approach should I choose instead to check whether the given_id exists in any object of the array?
Based on your usecase, i create this code sandbox: https://codesandbox.io/s/stackoverflow-answer-ke9drk?file=/src/index.ts
explanation:
Type wont compile, so we need something to mark what the interface of the object.
Also i may confused by your code shopApprovalData[resource] what do you want to achieve here? for example, if resource is str1 shopApprovalData[resource] will always return undefined because no index str1 in Array
I hope it help,
Best Regards
So I'm trying to learn writing more generic. I have POST/PUT/DELETE/GET for attatchments together with these entity types (there are also alot more entity types that I will need to add in the future).
This code works, and it is indeed more generic than writing 4 different getAttatchment with hardcorded personnel/workoder etc where it is ${apiType} currently. Some progress made atleast.
But how could I rewrite this even better? I would like to have e.g getAttatchments<T>(EntityType<T> .....) but I don't know how I could write it like that. And ofcourse it need to be typesafe so you don't actually pass entities that does not exist.
export enum EntityType {
Personnel = 'personnel',
Workorder = 'workorder',
Asset = 'asset',
AssetBooking = 'assetbooking',
}
async getAttachments(id: string | number, apiType: EntityType) {
return await this.get<AttachmentDetails[]>(
`attachment/${apiType}/${id}/attachment`
)
}
What you have already looks fairly generic but I would forgo the enum and use a union type instead. e.g.
type EntityType = 'personnel'|'workorder'|'asset'|'assetbooking'
type AttachmentDetails= any // whatever
// mock implementation
function get<T>( url:string) {
return ''
}
function getAttachments<T extends EntityType>(id: string | number, apiType: T) {
return get<AttachmentDetails[]>( `attachment/${apiType}/${id}/attachment` )
}
Playground
I have a struct and an array of my structs as follows
struct Products{
var ProductType: String
var ProductName: String
var ProductLink: String
}
var CleaningProductsArray = [Products]()
When I write to my array of structs the ProductName Variable inside it sometimes can be written by the user with trailing whitespaces. I would like to return a version of the CleaningProductsArray but with all instances of ProductName having any trailing whitespaces removed. I have been trying to achieve with map as below but does not return what I would like it to. What is the most efficient way to do this?
let trimmed = CleaningProductsArray.map{ $0.ProductName.trimmingCharacters(in: .whitespaces) }
Quick answer is:
let trimmed: [Products] = CleaningProductsArray.map { product in
var adjusted = product
adjusted.ProductName = product.ProductName.trimmingCharacters(in: .whitespaces)
return adjusted
}
As it was correctly mentioned in the comments, there are things you can improve in your overall code design.
You could start with converting your model to meet Swift naming standards, which means not using plural for Products since the objects of this type describe a single product, and removing the product prefix from properties since its obvious from the context that they describe a "Product". Ideally you would also make the properties immutable, to make passing them around safer (google "Benefits of immutability"). You should create some other object responsible for collecting all the data for your product objects.
struct Product {
let type: String
let name: String
let link: String
}
Also, you should never use uppercased names for your variables/constants/properties/functions in Swift, so it's best to replace the CleaningProductsArray with cleaningProductsArray for the sake of readability. Uppercased names are reserved for types. Also you might want to drop the Array suffix since it's obvious from the type that it is an array
var cleaningProducts = [Product]()
let trimmed: [Product] = cleaningProducts.map {
Product(
type: $0.type,
name: $0.name.trimmingCharacters(in: .whitespaces),
link: $0.link
)
}
I can not get only city and country as an output from googleautocomplete component using react.
The way to do this would be to specify the types parameter on the Google Places Autocomplete component. However, the limitation there is that you can only really specify one of the options for types:
You may restrict results from a Place Autocomplete request to be of a
certain type by passing a types parameter. The parameter specifies a
type or a type collection, as listed in the supported types below. If
nothing is specified, all types are returned. In general only a single
type is allowed. The exception is that you can safely mix the geocode
and establishment types, but note that this will have the same effect
as specifying no types.
source: https://developers.google.com/places/web-service/autocomplete#place_types
So the best option for your situation would probably be to use the (regions) type collection, but this will include more than just cities and countries such as neighborhoods. Another option would be to use the (cities) type collection which will include only cities.
I also highly recommend the react-geosuggest library if you want something pre-made to accomplish this as you can pass those as parameters and style it yourself.
<Geosuggest
types={['(regions)']}
/>
EDIT
I think I might have misunderstood the question a bit. If you're trying to figure out how to get the street address, city, and country out of the response you get from the Places API, you're going to have to submit an additional request.
Once the user selects the place from the list, you will have to get the place_id out of the original request and submit a Place Details request. One of the fields in the response will be address_component which has this very strange format. I posted an example of what this full format looks like here.
I made a simple converter function that will return the basic components of an address in a manageable format:
// ---------------------------------------------------------------------- //
// https://developers.google.com/maps/documentation/geocoding/intro#Types //
// ---------------------------------------------------------------------- //
// returns:
// {
// address_1
// address_2
// city
// state_code
// zip_code
// country
// }
function convertAddressComponents(addrComp) {
let newAddr = {};
let address_1 = [];
addrComp.forEach((el, i) => {
if (el.types.includes("post_box")) {
address_1.push(el.long_name);
} else if (el.types.includes("street_number")) {
address_1.push(el.long_name);
} else if (el.types.includes("route")) {
address_1.push(el.long_name);
} else if (el.types.includes("subpremise")) {
newAddr.address_2 = el.long_name;
} else if (el.types.includes("locality")) {
newAddr.city = el.long_name;
} else if (el.types.includes("administrative_area_level_1")) {
newAddr.state_code = el.short_name;
} else if (el.types.includes("postal_code")) {
newAddr.zip_code = el.short_name;
} else if (el.types.includes("country")) {
newAddr.country = el.long_name;
}
});
newAddr.address_1 = address_1.join(" ");
return newAddr;
}
Feel free to modify this to suite your needs.
I need to check the existence of some elements in an array as such
I have an array as such
ar = ['one','two','three']
I want to know how I can individually check the elements in the regular expression code below instead of "/something/" that would map through my array and check if they exist in graphQL one by one.
similar : allCockpitHello (filter: {Association : {value : {regex: "\/something/" }}} limit:2){
nodes{
Name{
value
}
}
You need to have the regex string as an input parameter to be used by the resolver, GraphQL is not going to do the filter for you, you need to do/call that logic in the resolver based on your inputs.
Based on your example, you could have something like this on the schema and resolver:
type Node {
name: String!
}
type NodeQueries {
nodes (filterRegEx :String): [Node]!
}
Once you have the input string on the resolver, the implementation of the filter mechanism is up to you.
const resolvers = {
...
NodeQueries: {
nodes: (parent, params) => {
const {filterRegEx} = params; // regex input string
const ar = ['one','two','three'];
// Create a RegExp based on the input,
// Compare the with the elements in ar and store the result...
// You might end up with ... res = ['one', 'three'];
// Now map the result to match your schema:
return _.map(res, name => ({name}) ); // to end up with [{name: 'one'}, {name: 'three'}]
}
}
...
}
GraphQL is not a magic bullet - it's only a query language, it 'transports' your needs to the engine (local client, remote server ...) where all the necessary processing takes place.
In this case you probably need to pass your array and expression as variables to the server (resolver). If processing is expensive results (similar relation) should be already defined, cached, preprocessed, etc.
If dataset is small you can do this entirely client-side - iterate over an array (fetched using graphql).