How to update object property which is an array? - javascript

I am working in a ReactJS project and have a filterGroupsData property in my state. This is an array of objects, each object has a filters property which is an array of string values. See below:
filterGroupsData:[
{"key":1532957059388,"id":1532957059388,"filters":[]},
{"key":1532957059612,"id":1532957059612,"filters":[]},
{"key":1532957059847,"id":1532957059847,"filters":[]}
]
How can I add elements to the filters property of a object with a given id?
I attempted to this but this results in overwriting the whole object with on value:
// update the filter array of the object with id == activeId
let updatedFilterGroupsData = filterGroupsData.map(filterGroupData => filterGroupData.id === activeId ? filterGroupData.filters.push('test') : filterGroupData)
this.setState({filterGroupsData: updatedFilterGroupsData});
Appreciate any help.

You can use findIndex to get the index of the filter group you want to update, and then create a copy of the object and the filters array and add a new entry to it.
Example
const id = 1532957059388;
this.setState(previousState => {
const filterGroupsData = [...previousState.filterGroupsData];
const index = filterGroupsData.findIndex(group => group.id === id);
filterGroupsData[index] = {
...filterGroupsData[index],
filters: [...filterGroupsData[index].filters, "new filter"]
};
return { filterGroupsData };
});

Here: filterGroupData.filters = 'test'
You're setting the prop value to a string instead of putting in the array.
You need to push the item into the filters array like:
filterGroupData.filters.push('test');

filters is a array so you need to use push('test') with multi line code inside map:
var filterGroupsData = [
{"key":1532957059388,"id":1532957059388,"filters":[]},
{"key":1532957059612,"id":1532957059612,"filters":[]},
{"key":1532957059847,"id":1532957059847,"filters":[]}
]
var activeId = 1532957059612;
let updatedFilterGroupsData = filterGroupsData.map((filterGroupData) => {
if(filterGroupData.id === activeId) {
filterGroupData.filters.push('test');
}
return filterGroupData
});
console.log(updatedFilterGroupsData);

Related

How to add and update objects into array of objects?

I am trying to dynamically add an object to an array of objects, I have been trying to Destructuring the main object but it adds a number to the end of the parent array. This is what I have:
const [data, setData] = useState ([
{
_id:1,
firstName:'Leo',
lastName:'Miller',
telephone:'+569273829',
mail:'leo.miller#gmail.com',
work:[
{_id:1, startWorkDate:'01/01/2015', endWorkDate:'01/02/2017', work:'description...'},
{_id:2, startWorkDate:'01/01/2018', endWorkDate:'01/02/2020', work:'description...'}
]
}];
I generate dynamically this object:
const value = {_id:3, startWorkDate:'01/01/2018', endWorkDate:'01/02/2020', work:'description...'}
I need to add it into data.work and after that update only the description of work._id[3]
I try with this function
const addNewWork = (value) => {
let copyData = [...data, data[0].workExperience.push(value)]
return setData(copyData)
}
but for some reason doesn't add correctly the object. Help please!
You have an array and not an object. Your statement
let copyData = [...data, data[0].workExperience.push(value)]
is doing two things:
mutating the state by doing push(). Which is not the react way.
creating a new array. Also adding a new item to the array, but that is the new length of data[0].workExperience.
The return value of Array.prototoype.push is:
The new length property of the object upon which the method was called.
What you have to do is:
Make a copy of the array. Can use ... (spread operator) here.
Make a copy of the array object you want (first index). Try to add the object to its specific property workExperience.
const addNewWork = (value) => {
let newData = [...data];
let newWorkExperienceArray =
[...data[0].workExperience,value];
let newDataFirstObject = {...data[0], workExperience : newWorkExperienceArray};
newData[0] = newDataFirstObject;
return setData(newData)
}
You can also update the property. I didn't find the relevant code in your question as to what I have to update so I didn't update anything in the third workExperience object.
EDIT: It seems in your code the property name is work and not workExperience. Please confirm. The above code uses workExperience, you can replace it by work if that is the case
You can do this with this simple function:
const addNewWork = (value) => {
let updatedObj = data[0];
updatedObj.work.push(value)
// updates your object each time
let copyData = [updatedObj]
// adds a new object for each call
// let copyData = [...data, updatedObj]
return setData(copyData)
}
Now it updates the object in your state. If you want to add a new object for each call just uncomment let copyData = [...data, updatedObj] and comment out let copyData = [updatedObj]
When you set state for array your setter is a quite bite different
setData(prevData => [...prevData, newItem]) // to add a single item to array
setData(prevData => newArray) // to replace entire array

Removing object with property in array leaves an empty object

I'm trying to remove an item with a property from array object based on the key but it is leaving an empty object. For example,
var items = [{"fruits": ["Apple","Banana"]},{"veggies": ["Potato","Carrot"]}]
So I want to remove the item with the fruits property. This is the code I tried...
var filter = items.map(({ fruits, ...rest }) => rest);
This gave me an output of
[{},{"veggies": ["Potato", "Carrot"]}]
Why is it leaving a trace of an empty object? And how to get rid of that empty object?
Please use filter function.
var items = [{"fruits": ["Apple","Banana"]},{"veggies": ["Potato","Carrot"]}];
const result = items.filter(val => !val.hasOwnProperty("fruits"));
console.log(result);
Try this
var items = [{"fruits": ["Apple","Banana"]},{"veggies": ["Potato","Carrot"]}]
console.log(items.filter(item => !item.hasOwnProperty('fruits')))
.map will return an array of the same length, mapped to a new array. To remove entries use .filter:
var items = [{"fruits": ["Apple","Banana"]},{"veggies": ["Potato","Carrot"]}]
var filter = items.filter(i => !i.fruits);
console.log(filter);

How to push new elements to a nested array of objects in JavaScript using spread syntax

I want to create object like this
var items = [{'2021-07-06':[{todo:'Hello'},{todo:'World'}]}]
Here the date should be dynamic so I tried to push value to it like this but this doesn't work
{...items, [CurrentDate] : {...[CurrentDate], todo:'I am here'}}
[CurrentDate] refers to the current date here which is '2021-07-06' and push new todo in array. Also if the date key not present then I want to add new Date eg if '2021-07-08' is not present then add to object and add new todo to it.
You first have to find the right element in items to update (e.g. using findIndex), then access it by index. Then you can update that object using spread syntax.
However, spread is an inefficient approach as it creates a duplicate object for no reason. Likely push is much more efficient (and semantic) as it just adds an element to the array.
The following also handles the case where currentDate doesn't exist in the items array.
let items = [{'2021-07-06': [{todo: 'Hello'}, {todo: 'World'}]}];
function updateItems(items, key, newItem) {
// Find the right object in items
let idx = items.findIndex(obj => obj.hasOwnProperty(key));
// If not found, append a new object
if (idx == -1) {
items = [...items, {[key]: newItem}];
// Otherwise, update existing object
} else {
items[idx] = {
[key]: [...items[idx][key], newItem]
};
}
// Unnecessary but handy
return items;
}
// Update existing object
updateItems(items, '2021-07-06', {todo: 'new item'});
console.log('Update existing item\n' + JSON.stringify(items));
// Add new object
// If using spread, must keep new array returned by updateItems
items = updateItems(items, '2021-07-07', {todo: 'new key and item'});
console.log('Add new item\n' + JSON.stringify(items));
Spread also creates a shallow copy, whereas push doesn't affect any existing elements in the array and is less code to type.
it is easy.
var items = [
{
'2021-07-06':[
{todo:'Hello1'},{todo:'World1'},
{todo:'Hello2'},{todo:'World2'},
{todo:'Hello3'},{todo:'World3'},
{todo:'Hello4'},{todo:'World4'},
],
'2021-07-07':[
{todo:'Hello11'},{todo:'World11'},
{todo:'Hello22'},{todo:'World22'},
{todo:'Hello33'},{todo:'World33'},
{todo:'Hello44'},{todo:'World44'},
]
}
];
let's imagine we want to add
'2021-07-08':[
{todo:'Hello111'},{todo:'World111'},
{todo:'Hello222'},{todo:'World222'},
{todo:'Hello333'},{todo:'World333'},
{todo:'Hello444'},{todo:'World444'},
]
the way we would do so is like this
const newItem = '2021-07-08':[
{todo:'Hello111'},{todo:'World111'},
{todo:'Hello222'},{todo:'World222'},
{todo:'Hello333'},{todo:'World333'},
{todo:'Hello444'},{todo:'World444'},
];
const newTodo = {todo:"Hello5"};
///....
items = [...items, newItem];
/**
* IF YOU WANT TO ADD AN OBJ TO A DATE, DO IT LIKE THIS
*/
items[0]=[...items[0], newTodo];
items is an array, so you need to loop'em items to find the correct index
for (let i=0; i < items.length; i++) {
// before doing the next step validate if the items at position i is equals to an array
const currentItem = [...items[i]];
if (currentItem.anythingYouThinkWouldBeCondition === true) {
currentItem.push(newTodo);
items = [...items,currentItem];
break;
}
}

What is wrong in the following comparing and object property implementation it returns just 2 value (JS)?

I am trying to check if the first array includes the object that has the same id as the first element in the second array. Then for that object in the first array add the following 2 property values.
I tried the following but it returns only an array of that new values instead of returning the full first array of objects that includes that modified object with new properties.
products = products
.filter(item => item.id === productsByTags[0].id)
.map(item => (item.tags = 'shoes'), (item.keywords = 'black'))
How can I get the full array of objects where those 2 new properties, values are added to that object which has the same id based on above condition?
You need to return a new objectby spreading the actual object and two new properties.
.map(item => ({ ...item, tags: 'shoes', keywords: 'black' }))
The problem you are running into is that both .filter and .map return new arrays. So once you have filtered, you have already removed all items that do not match your check. If you move it all into a single map, you can mutate only the items that you want to while still returning the none mutated items as well.
products = products.map(item => {
let newItem = {...item};
if(item.id === productsByTags[0].id){
newItem.tags = 'shoes';
newItem.keywords = 'black';
}
return newItem;
})
products = products
.filter(item => item.id === productsByTags[0].id)
.map(item => {
item.tags = 'shoes';
item.keywords = 'black';
return item;
});
Post filtering the data you were trying to add the new properties to object so you should return the object to map to return you array of objects.

array.map() is not a function reactjs

I have a function which stores data after splicing from an array.
const removedItemstax = {};
function findAndRemove1(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
var removedItem= array.splice(index, 1);
removedItemstax.push(removedItem);
}
});
}
When I try to get map it using below code to get distinct values const tax = removedItemstax.map(d => d.taxId) I'm getting an error that .map() is not a function.
But when I push the array removedItemstax to console I get to see all the elements stored within it.
I get the same error when I pass the array removedItemstax = {} via props after setting a state to it.
Mapping returns undefined, however pushing it directly displaying complete data assigned to the array. I am following the regular method to map.
You can try this way:
const removedItemstax = [];
function findAndRemove1(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
var removedItem = array.splice(index, 1);
removedItemstax.push(removedItem);
}
});
}
Instead removedItemstax be a object, him can to be a array
I figured out the reason for getting undefined elements when mapping. This is due to a multidimensional array being stored in attribute const removeItemstax = [].
I'm using the below command to flatten the multidimensional array into a normal array before mapping it.
Here's the syntax:
const removedItemstax1 = [].concat.apply([], removedItemstax);

Categories

Resources