update object value in useState array nested - reactjs

I have a nested value in array and I want to update value using useState and it is updated but it also create new index value in array which is not required.
let data = {
query: [
{
com: "",
id: 1,
rules: [{ fN: "tej", sN: "raj" }]
},
{}
]
};
here I want to update value of fN only but new index [1] created in query at same time. here is link to code - https://codesandbox.io/s/blissful-night-kkycxh?file=/src/App.js:103-239

I would do as below, using a state update function, as you are trying just with index 0 it doesn't really matter
useEffect(() => {
setQuery((prev)=>{
return prev.map((q,idx)=>{
if(idx === 0){
q.rules[0].fN = "ram"
}
return q
})
});
}, []);

Related

How to return objects that have matching value when comparing to a separate array

In my state I have an object called foodLog which holds all entries a user enters with one of the keys being foodSelectedKey and I'm trying to return all entries that have a matching value from that key with a different array called foodFilter.
However, this doesn't work and errors out saying foodLog.filter() isn't a function - I've looked this up and it's because it's an Object (I think). Any help would be greatly appreciated!
state = {
// log food is for the logged entries
foodLog: {},
// used for when filtering food entries
foodFilter: [],
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.filter((item) => {
return foodLog.foodsSelectedKey.map((food) => {
return foodFilter.includes(food);
});
});
};
I guess the reason behind the error Is not a function is that the object can not be looped. By that it means you can not iterate an object with differend variables inside, if it has no index to be iterated like an array. The same goes for map(), find() and similar functions which MUST be run with arrays - not objects.
As far as I understand you have an object named foodLog which has an array named foodsSelectedKey. We need to find intersected elements out of foodFilter with the array. This is what I came up with:
state = {
// log food is for the logged entries
foodLog: {
foodsSelectedKey: [
{ id: 1, name: "chicken" },
{ id: 2, name: "mashroom" }
]
},
// used for when filtering food entries
foodFilter: [
{ id: 1, name: "chicken" },
{ id: 2, name: "orange" }
]
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.foodsSelectedKey.filter((key) =>
{
for (let i=0; i<foodFilter.length;i++){
if(foodFilter[i].name===key.name)
return true
}
return false;
}
);
return matched;
};
The Output is filtered array, in this case, of one element only:
[{
id: 1
name: "chicken"
}]
In order to check the output - run console.log(findMatches()). Here is the CodeSandbox of the solution. (check console at right bottom)

Insert list data over the iteration(map)

Here I am trying to modify my data over the iteration and send some result to API call.
The API Call receives a request with a structured data format which is
{ list: [{ id: "1", name: "Hello" }, ... ] }
Somehow I managed to call the API with single data ( const params in my current code, it only accepts single data).
But now it has to be done with multiple data something like this:
{ list: [{ id: "1", name: "Hello" }, { id: "22", name: "Ed" }, { id: "36", name: "Jason" } ... ] }
Here is my current code
const [table, setTalbe] = useState(..); // assume, we have some table data here
const processNow = () => {
let id = 0;
let name = '';
// if table length is greater than 1, we go for the loop.
if (table.length >= 1) {
table.map(data => {
id = data.userId;
name = data.userName;
});
//insert table data to params, here I want to add whole table data into "list"
//the final result of this list should be something like this
//ex ) list: [{ id: '123', name: 'Josh' }, { id: '125', name: 'Sue' }, { id: '2222', name: 'Paker' } ...],
// but how??
const params: any = {
list: [
{
id: id,
name: name
},
],
};
//send PUT reqeust with params
axios
.put(
'/api/v1/tosent',
params,
)
.then(res => {
console.log('The response', res);
})
.catch(err => {
console.log('The error: ', err);
});
}
};
but I'm stuck with it, please help me to finish this code to work properly.
need your kind advice.
Array.prototype.map returns a new array with the function you pass applied to every element. You should study the MDN documentation on map to understand its use.
Your current code does nothing with the map return value:
table.map(data => {
id = data.userId;
name = data.userName;
});
You probably assumed .map would mutate the data, as in change it in place. Instead, the whole operation returns a new array.
It looks like you want to do:
const list = table.map(data => {
return {
id: data.userId,
name: data.userName
}
});
This is applying a function to every element in the array that will map each element to a new object, matching your question, with an id and name key. Then it looks like you want to pass the returned value of map (which we named list above) to your call:
const params: any = {
list: list
};

Typescript - Querying or flattening nested array but keeping some objects as nested ones

Again I'm stuck with a nested Array of objects. I want to flatten it out, but I do have to keep some nested objects. The Problem I'm running into: How to rename the keys of the nested objects since I have an undefined number of nested objects. There might be 3 of them oder 8. So property1_3 has to be renamed to eg property1_3_1, property1_3_2 - depending on how many objects are in the original json data. And how to aply them to the correct parent object.
The json data I recieve looks like:
data = [{
"property1_1": "value1_1",
"property1_2": "value1_2",
"property1_3": [
[{
"subproperty1_1_1": "subvalue1_1_1",
"subproperty1_1_2": "subvalue1_1_2"
}],
[{
"subproperty1_2_1": "subvalue1_2_1",
"subproperty1_2_2": "subvalue1_2_2"
}]
]
},
{
"property2_1": "value2_1",
"property2_2": "value2_2",
"property2_3": [
[{
"subproperty2_1_1": "subvalue2_2_1",
"subproperty2_1_2": "subvalue2_2_2"
}],
[{
"subproperty2_2_1": "subvalue2_2_1",
"subproperty2_2_2": "subvalue2_2_2"
}],
[{
"subproperty2_3_1": "subvalue2_2_1",
"subproperty2_3_2": "subvalue2_2_2"
}]
]
}
]
What I want to achieve now is:
data = [
{
"property1_1": "value1_1",
"property1_2": "value1_2",
"property1_3_index1": {"subproperty1_1_1":"subvalue1_1_1", "subproperty1_1_2":"subvalue1_1_2"},
"property1_3_index2": {"subproperty1_2_1":"subvalue1_2_1", "subproperty1_2_2":"subvalue1_2_2"}
},
{
"property2_1": "value2_1",
"property2_2": "value2_2",
"property2_3_index1": {"subproperty2_1_1":"subvalue2_2_1", "subproperty2_1_2":"subvalue2_2_2"},
"property2_3_index2": {"subproperty2_2_1":"subvalue2_2_1", "subproperty2_2_2":"subvalue2_2_2"},
"property2_3_index3": {"subproperty2_3_1":"subvalue2_2_1", "subproperty2_3_2":"subvalue2_2_2"}
}
]
My last try was:
transformData(input) {
const testArray = [];
input.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (const [index, element] of obj[prop].entries()) {
testArray.push(element[0]);
}
}
}
});
}
but this only leeds to an array with all the single subobjects in one array. I'm also not quite sure if it's best trying to convert the original data or to build a new array as I tried before.
I finally found a way to achieve this.
transformData(input) {
return input.map(obj => {
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && Array.isArray(obj[prop])) {
for (let i = 0; i < obj[prop].length; i++) {
const name = prop + (i + 1).toString();
obj[name] = obj[prop].flat(1)[i];
}
delete obj[prop];
}
}
return obj;
});
}

Loop and merge object in Lodash

I have a array of object, like this:
var obj = [{
employeeId: 1300000,
requestValue: 2
}, {
employeeId: 1300000,
requestValue: 3
}, {
employeeId: 1300001,
requestValue: 4
}]
I know how to do it in javascript. But, How can I a retrieve the following result using Lodash:
var result = {
1300000: [
{ requestValue: 2 },
{ requestValue: 3 }
],
1300001: [
{ requestValue: 4 }
]
}
Using Lodash:
Group By with employeeId
mapValues to map each group, and take only requestValue by using
map
Here is the example:
let input = [{"employeeId":1300000,"requestValue":2},{"employeeId":1300000,"requestValue":3},{"employeeId":1300001,"requestValue":4}],
res = _(input)
.groupBy('employeeId')
.mapValues(g => _.map(g, ({requestValue}) => ({requestValue})))
.value();
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Using Plain JavaScript
Take a hash (resulant) and start with iterating it using reduce
Check if the employee id exists as a key of the hash for each
employeeId, if exist use it otherwise create the key value pair with
a empty array
Take either the existing value (for the key) or the new one and push
requestValue
let input = [{"employeeId":1300000,"requestValue":2},{"employeeId":1300000,"requestValue":3},{"employeeId":1300001,"requestValue":4}],
res = input.reduce((r, {employeeId, requestValue})=> {
(r[employeeId] = r[employeeId] || []).push({requestValue});
return r;
}, {});
console.log(res);

Add a Property to an Array of Objects from a Mongoose Find() query [duplicate]

This question already has answers here:
Why can't you modify the data returned by a Mongoose Query (ex: findById)
(3 answers)
Closed 4 years ago.
I am returning an array of document objects from a Mongoose query. The array is populated with expected results.
[{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy'
}]
I am trying to add a new property on to certain objects only where a criteria is met. I've tested this element and the conditional logic is also performing as expected. I loop through the array above and another, larger array to find matching ids. When a match is found, I need to add a property, for example:
{isArchived: true}
to the object in the array returned by the find() query. So I should end up with:
[{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy',
isArchived: true
}]
The problem is that no matter what I try I cannot get the new property added onto the specific object within the array.
I have tried just about every 'Add property to an object' answer on here, so am just about ready to start throwing things!!
Thanks for any and all help!
EDIT: The entire router code is as follows:
router.get('/edit/:id', ensureAuthenticated, (req, res) => {
Menu.findOne({ _id: req.params.id })
.populate('recipes')
.then(menu => {
Recipe.find({user: req.user.id}, function (err, allRecipes) {
if(menu.user != req.user.id){
req.flash('error_msg', 'Not Authorised!');
res.redirect('/menus');
} else {
//use momentjs to format dates to YYYY-MM-DD
const vFromDate = moment(menu.validFrom).format('YYYY-DD-MM');
const vToDate = moment(menu.validTo).format('YYYY-DD-MM');
const selectedRecipeIds = menu.recipes.map(id => id._id);
for (var i = 0; i < allRecipes.length; i++){
for (var j = 0; j < selectedRecipeIds.length; j++){
if (JSON.stringify(allRecipes[i]._id) == JSON.stringify(selectedRecipeIds[j]._id)) {
allRecipes[i].isSelected = true
}
}
}
res.render('menus/edit', {
menu,
vFromDate,
vToDate,
allRecipes
});
}
});
})
});
a = [{
_id: 1,
name: 'Mayonnaise'
},
{
_id: 2,
name: 'Gravy'
}]
a[0].isArchived = true
I think you are trying to mutate the original objects that came from the response.
Try to operate on a copy, like this:
const allRecipiesCopy = [...allRecipies]
And then loop over this array, and mutate these objects, not original ones.

Resources