Take the following example:
getOptions() {
let options = {};
if (this.props.location.hasOwnProperty('query')) {
const query = this.props.location.query;
const queriesMap = {
'createdBy': 'createdBy',
'state': 'state',
'created_from': 'created_at[from]',
'created_to': 'created_at[to]'
};
Object.keys(query).map(function(key) {
if(queriesMap.hasOwnProperty(key)) {
options = Object.assign(options, { queriesMap[key]: query[key] });
}
});
}
return options;
}
I'm using the queriesMap object to map url parameters to build a new url to call an API. The problem is that query is undefined when I'm trying to access it from within the .map callback.
How do I access the query variable?
Looks like you are missing a [] around queriesMap[key]. So it should be options = Object.assign(options, { [queriesMap[key]]: query[key] });.
Also, you could just do options[queriesMap[key]] = query[key] rather than Object.assign
Related
Using the following JSON object, how can I pass the "datapath" property for each of the dropdown within just one _.get method of lodash?
JSON
"dropdownList": {
"dropdown1": {
"text":"Disaster",
"datapath":"data.disaster"
},
"dropdown2": {
"text":"Process",
"datapath":"data.process"
},
"dropdown3": {
"text":"Subqueue",
"datapath":"data.subqueue"
}
}
for example, this is what I have right now which only contains the datapath for dropdown1:
const mapStateToProps = (state, ownProps) => {
let data = _.get(state, ownProps.dropdownList.dropdown1.datapath);
if (data == null) {
data = _.get(state, "common." + ownProps.dropdownList.dropdown1.datapath);
}
let options = _.get(
state,
ownProps.dropdownList.dropdown1.datapathRead,
_.get(state, "common." + ownProps.dropdownList.dropdown1.datapathRead, {
key: "key",
value: "value",
text: "text",
})
);
return { data: data, datapathOptions: options };
};
How can I write the above code better so that I can pass the datapath for for all 3 dropdowns in the same get method?
Convert your JSON Object to JSON array using the below code.
const newData = [...ownProps.dropdownList];
and pass newData to your method where you can use any loop to do your work simple
I am using eslint and getting this error.
Expected to return a value in arrow function
The error is showing on the third line of the code.
useEffect(() => {
let initialPrices = {};
data.map(({ category, options }) => {
initialPrices = {
...initialPrices,
[category]: options[0].price,
};
});
setSelectedPrice(initialPrices);
}, []);
The map function must return a value. If you want to create a new object based on an array you should use the reduce function instead.
const reducer = (accumulator, { category, options }) => (
{...accumulator, [category]:options[0].price}
)
const modifiedData = data.reduce(reducer)
More information https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
The map function is intended to be used when you want to apply some function over every element of the calling array. I think here it's better to use a forEach:
useEffect(() => {
let initialPrices = {};
data.forEach(({ category, options }) => {
initialPrices = {
...initialPrices,
[category]: options[0].price,
};
});
setSelectedPrice(initialPrices);
}, []);
Your map function should return something. Here it's not the case so the error happens. Maybe a reduce function will be more appropriate than map?
From what I can see in your case, is that you want to populate initialPrices, and after that to pass it setSelectedPrice. The map method is not a solution, for you in this case, because this method returns an array.
A safe bet in your case would a for in loop, a forEach, or a reduce function.
const data = [
{
category: "ball",
options: [
{
price: "120.45"
}
]
},
{
category: "t-shirt",
options: [
{
price: "12.45"
}
]
}
];
The forEach example:
let initialPrices = {};
// category and options are destructured from the first parameter of the method
data.forEach(({ category, options}) => {
initialPrices[category] = options[0].price;
});
// in this process I'm using the Clojure concept to add dynamically the properties
setSelectedPrice(initialPrices);
The reduce example:
const initialPrices = Object.values(data).reduce((accumulatorObj, { category, options}) => {
accumulatorObj[category] = options[0].price
return accumulatorObj;
}, {});
setSelectedPrice(initialPrices);
I'm trying to concatenate all the query params string that I have into a one final query including all params but I keep getting this result :
_filter=0=((startDate=ge=2019-09-30T22:00:00.000Z);(endDate=le=2019-10-
03T22:00:00.000Z));1=
(category=eq=Warning,category=eq=Error);&_limit=50&_sort=asc
with the annoying 0=, 1=, 2=, ....
The expected result is to be like that :
_filter=((startDate=ge=2019-10-06T12:39:05.000Z;endDate=le=2019-10-
07T23:59:59.999Z);(category=eq=ALERT,category=eq=META))"
Here is my code:
generateQueryString(obj: any) {
let query = [];
if (obj.startDate && obj.endDate) {
query = query.concat(this.buildDateQueryString(obj.startDate, obj.endDate)
);
}
if (obj.category) {
query = query.concat(this.buildCategoryQueryString(obj.category));
}
return query;
}
Let us assume you want pass some data like
const userData = {
firstName: 'Arpit',
lastName: 'Patel'
}
You can pass this object into Query Params like this.
this.router.navigate(['/dashboard/details'], { queryParams: { user: JSON.stringify(userData) } });
Then extract this Object in next component which is called as below.
this.route.queryParams.subscribe(params => {
const user= JSON.parse(params.user);
console.log(user);
});
This will result in JSON object. You can access it directly.
I'm using the following code to get object from react state.
const { organizations } = this.state;
The sate object is as following.
this.state = {
userOrganizations: {},
OrganizationUsers: {}
}
userOrganizations is actually an object with an inner object named organizations. How can I map this using es6 code?
Edit
What I actually need is to get inner objects of both the userOrganizations and OrganizationUsers using the following code.
const { organizations, users } = this.state;
The organizations and users are sub objects which are inside the userOrganizations and OrganizationUsers.
So when I want to handle them, will they work with just calling
const { organizations, users } = this.state.userOrganizations, this.state.OrganizationUsers;
You can nest destructruring like
const { userOrganizations : { organizations } } = this.state;
or simply write
const { organizations } = this.state.userOrganizations;
This is so simple but still many got it wrong. Here is an example of inner destructuring
const obj = {
someArray: [ 1, 2, 3],
someInnerObj : {num: 123, txt: 'text'}
}
const {someArray: [first,second], someInnerObj: { num: myNum, txt: meText}} = obj
console.log(first,second,myNum,meText)
Try it in console
Just use dot notation until you get to the parent object just above the property you want
const obj = { outer: { inner: 'value' }};
const { inner } = obj.outer;
console.log(inner);
To destructure more than one thing at a time in different nested levels, try something like:
const x = {
state: {
userOrganizations: {
organizations: 'orgValue'
},
OrganizationUsers: {
users: 'userValue'
}
}
}
const { userOrganizations: { organizations }, OrganizationUsers: { users } } = x.state;
console.log(organizations + ' ' + users);
If i'am not wrong this should solve your issue,
const { organizations } = this.state.userOrganizations;
I'm receiving params from my get request that looks like this:
{ location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' }
I then query a mongodb database that loops through each of the key and value pairs and queries for their union in the database.
I then save the returned values to outputCaption and then use a callback to pass the outputCaption back.
The problem is the callback gets called as many times as their key-value pairs looped over.
I'm forced to do this because I need the callback inside the db.Phrase.find call but I call that multiple times...
So I've fixed it using the code in app.get (I wait until all the keys have defined values in outputCaption before doing anything)
It works, but I can't imagine it's the best way to do it so I'm hoping there's a less hackish way?
Thanks
server.js
var express = require('express');
var db = require('./modules/db')
var logic = require('./modules/logic')
...
app.get('/phrase', function(req, res){
logic(req.query, function(outputCaption){
var flag = true
for (key in outputCaption){
if (outputCaption[key] === null){
console.log('Incomplete')
var flag = false;
}
}
if (flag === true) {
console.log(outputCaption);
};
});
})
...
logic.js
var db = require('./db')
var logic = function(params, callback){
var outputCaption = {
who: null,
what: null,
location: null,
weather: null
};
for (key in params){
category = key.toLowerCase();
option = params[key].toLowerCase();
db.Phrase.find({$and: [
{category: category},
{option: option}
]}, function(err, phrases){
if (err) return console.error(err);
var options = Object.keys(phrases).length
var idxOfOptionPicked = Math.floor(Math.random() * options)
outputCaption[phrases[idxOfOptionPicked].category] = phrases[idxOfOptionPicked].phrase
callback(outputCaption)
})
}
}
module.exports = logic;
Instead of firing multiple queries and performing a union of the result at the client side, make use of the query operators to allow MongoDB to do the union for you.
That way you:
Avoid multiple hits to the database.
Avoid multiple callback handlers.
Can post process the results in a single callback handler.
You can modify your code to prepare a query object from the request parameter,
var params = {location: 'Venice', weather: 'Dry', what: 'Yoga', who: 'Bob' };
var query = {};
var conditions = [];
Object.keys(params).forEach(function(key){
var $and = {};
$and["category"] = key.toLowerCase();
$and["option"] = params[key];
conditions.push($and);
});
(conditions.length > 1)?(query["$or"] = conditions):(query = conditions[0]);
Now the constructed query looks like:
{ '$or':
[ { category: 'location', option: 'Venice' },
{ category: 'weather', option: 'Dry' },
{ category: 'what', option: 'Yoga' },
{ category: 'who', option: 'Bob' }
]
}
You can pass this object to the find() method, to get the results in a single hit:
db.Phrase.find(query,callback);
This way your code remains cleaner and easier to understand.