How do I update array inside object in redux - javascript

I have an array I'm writing a code for redux now.
const initialState = [{ id: '1', title: '', description: '' }];
I would like to update that array like this
[{ id: '1', title: '', description: '' },{ id: '2', title: '', description: '' }];
and after copying I want to update the copy one of id to '2'
here is what I tried
case COPY_QUESTION: {
const copyQuestion = state.find(question => question.id === action.payload)
copyQuestion?.id = (state.length + 1).toString()
return [...state, copyQuestion];
}
it didn't work for me. if I try to change id, the 0 index changes too at the same time. like this
[{ id: '2', title: '', description: '' },{ id: '2', title: '', description: '' }];
I would really appreciate your help thanks for reading this question.

JavaScript handels Objects by reference and therefore ’find’ only returns the address in memory of the already existing object, which you then manipulate.
You have to clone your object first, e.g. using the spread operator (not for deep clones):
const originalQuestion = state.find(question => question.id === action.payload)
const copyQuestion = { ...originalQuestion }
Have a look at this SO question for more context and possibilities.

Something like this should work:
const initialState = [{ id: '1', title: '', description: '' }];
const copyInitialState = [...initialState]
copyInitialState.push({ id: parseInt(copyInitialState[copyInitialState.length - 1].id, 10) + 1, title: '', description: '' })
//setState
copyInitialState is then equal to:
[
{
id:"1",
title:"",
description:""
},
{
id:2,
title:"",
description:""
}
]

Related

How to remove data with same id in an array of object using javascript?

in an arry of objects i want to remove object which have same id (duplicated data) using javascript.
below is the input array
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
so as you see from above array there are duplicating data with id '1' and '2'.
if there is similar id i want include only one
so the expected output is like below,
const output = [
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
]
how can i do this. could someone help me with this. i am new to programming thanks.
You can use reduce to filter data from the array based on some condition like bellow
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = input.reduce((accumulator, current) => {
let exists = accumulator.find(item => {
return item.id === current.id;
});
if(!exists) {
accumulator = accumulator.concat(current);
}
return accumulator;
}, []);
console.log(result);
Similar to this answer. You will have to change the const to let while declaring input though, or use a new variable I suppose.
filtered_input = input.filter((value, index, self) =>
index === self.findIndex((t) => (
t.id === value.id
))
)
There is a lot of good approachs here.
Here is my approach for removing matching property from the original array and sending it back in the return if found.
I prefer to use this one, if you are looping through a external array and matching them, this way you dont need to loop through the whole array again and again for each, because while you are finding the matches it keeps removing them from the original array, increasing performance.
Note that this will return the first match found
let id = "601985b485d9281d64056953"
let contacts = [{
...,
parent: "601985b485d9281d64056953",
...,
},
{
...,
parent: "601985b485d9281d64065128",
...,
}
]
function findAndRemoveObjectFromArray(array, internalProperty, externalProperty, convertType = "string", returnObject = false) {
let objIndex = -1
if (convertType === "string") objIndex = array.findIndex((obj) => String(obj[`${internalProperty}`]) === String(externalProperty));
if (convertType === "number") objIndex = array.findIndex((obj) => Number(obj[`${internalProperty}`]) === Number(externalProperty));
if (objIndex > -1) {
const object = array.splice(objIndex, 1);
if (returnObject) return object.shift()
return object
}
return [];
}
let currentContact = findAndRemoveObjectFromArray(contacts, "parent", id, 'string', true)
// Results:{..., parent: "601985b485d9281d64056953",...}
you could use Set to get rid of the duplicate data like this
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = [...new Set(input.map(JSON.stringify))].map(JSON.parse)
console.log(result)
Below is another approach
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
];
const uniqueIds = new Set();
const uniqueList = input.filter(element => {
const isDuplicate = uniqueIds.has(element.id);
uniqueIds.add(element.id);
return !isDuplicate;
});
console.log(uniqueList);

Javascript Array doesn't map correctly

I'm "consolling" the entire code... but I can't find any issue, only a weird behaviour.
Let me explain:
I've an angular component (let's call it parent) which send some tags to his child through a inputTags array.
Then I need to set another list with ALL the tags of the user, called allTags.
The array (both inputTags and allTags) is formatted like this:
{ id: 'tagId', name: 'tagName' }
I need to make an unified array of those two. The expected output should contain an array of items that it's formatted like this: { id: 'tagId', name: 'tagName', selected: boolean }
In order to do this I'm mapping the allTags array in this way:
Let's suppose that:
inputTags = [
{ id: 'work', name: 'Work' },
{ id: 'motivation', name: 'Motivation' }
];
allTags = [
{ id: 'network', name: 'Network' },
{ id: 'work', name: 'Work' },
{ id: 'smart', name: 'Smart' },
{ id: 'motivation', name: 'Motivation' }
];
Now... allTags are actually retrived from a server, so my code looks something like this:
this.tagsService.getAll().subscribe(tags => {
this.allTags = tags.map(tag => {
let select = false;
this.inputTags.forEach(inputTag => { select = (inputTag.id === tag.id) })
return {
id: tag.id,
name: tag.name,
selected: select,
};
});
})
This for me seems quite standard, but in fact NO, because instead of getting:
allTags = [
{ id: 'network', name: 'Network', selected: false },
{ id: 'work', name: 'Work', selected: true }, // is selected
{ id: 'smart', name: 'Smart', selected: false },
{ id: 'motivation', name: 'Motivation', selected: true } // is selected
];
I get this:
allTags = [
{ id: 'network', name: 'Network', selected: false },
{ id: 'work', name: 'Work', selected: false }, // is NOT selected
{ id: 'smart', name: 'Smart', selected: false },
{ id: 'motivation', name: 'Motivation', selected: true } // is selected
];
Basically the issue is that it's selecting only one tag, not multiple tags.
You can try some:
this.allTags = tags.map(tag => {
return {
id: tag.id,
name: tag.name,
selected: this.inputTags.some(inputTag => inputTag.id === tag.id)
};
});
JavaScript Array map() Method
*)creates a new array with the results of calling a function for every array element and it calls the provided function once for each element in an array, in order.
Note: map() Method does not execute the function for array elements without values and it does not change the original array.
Try the following:
this.allTags = allTags.map(tag => ({
id: tag.id,
name: tag.name,
selected: inputTags.some(i => i.id === tag.id),
}))

Merge object arrays with matched secondary object nested inside root of the primary object

I have two object arrays that i need to match based on a key [ContactID]. I'd like to add the matched secondary object (if there is one) as a nested document rather than into the root of the primary object. This is what my current solution does. Any help on this would be greatly appreciated. thanks
let primaryData = [{ ContactID: 'abc-def', Name: 'Test'}, { ContactID: 'ghi-jkl', Name: 'Test 2'}]
let secondaryData = [{ _id: '1', name: 'Test', ContactID: 'abc-def'}]
let final = primaryData.map(function(item){
return Object.assign(item, secondaryData.find(({ContactID}) => ContactID == item.ContactID));
});
Current Output
[{
ContactID: "abc-def" ,
Name: "Test" ,
_id: "1" ,
name: "Test"
},
{
ContactID: "ghi-jkl" ,
Name: "Test 2"
}]
Desired Output
[{
ContactID: "abc-def" ,
Name: "Test" ,
secondaryData: {
_id: "1" ,
name: "Test",
ContactID: "abc-def"
}
},
{
ContactID: "ghi-jkl" ,
Name: "Test 2"
}]
Object.assign won't add properties to your field it just merges the two objects. You can add the secondaryData key for when it exists like so
item['secondaryData'] = ...
let primaryData = [{ ContactID: 'abc-def', Name: 'Test'}, { ContactID: 'ghi-jkl', Name: 'Test 2'}]
let secondaryData = [{ _id: '1', name: 'Test', ContactID: 'abc-def'}]
let final2 = primaryData.map(function(item){
const secondaryFind = secondaryData.find(({ContactID}) => ContactID == item.ContactID);
//If item exists in secondaryData add it to secondat=ryItem to current item
secondaryFind && (item['secondaryData'] = secondaryFind);
return item;
});
let primaryData = [{
ContactID: 'abc-def',
Name: 'Test'
}, {
ContactID: 'ghi-jkl',
Name: 'Test 2'
}]
let secondaryData = [{
_id: '1',
name: 'Test',
ContactID: 'abc-def'
}]
console.log(primaryData.map(function(item) {
var second = secondaryData.filter(s => s.ContactID === item.ContactID);
if (second.length)
item.secondaryData = second;
return item;
}));

How to update the array in the react native?

How to update the array by changing one of the objects?
This will be my array code
this.datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
So now i want to write a function to update the reason like {reason: any reason} which from the index 1, index 2 remain the same.
So Far i had tried these
setReason = reason => {
let data = [...this.state.nameList];
let ind = data.findIndex(el => el.index === 'number');
data[ind] = { ...data[ind], reason: reason };
this.setState({
nameList: data
});
};
To update a single object data of an array
You need to first know the index of the object in the array which you want to update
eg Want to update first object of array
this.datas[0].reason = 'My custom reason';
Now you want to update the object of an array by finding the object in array you have to add a loop in it
eg: Update reason where name = Chris
for(i=0; i<this.datas.length; i++){
if(this.datas[i].name=='Chris'){
this.datas[i].reason = 'My custom reason';
break;
}
}
you can use map function on array.
let data = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
data = data.map(obj=>{
return{
...obj,
reason: 'any reason',
}
})
You can use of in the for loop and update the property value in an array, this is the working solution of your question.
var datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
for(data of datas){
data["reason"] = "any reason";
}
console.log(datas);
Try this
var datas = [
{
index: 1,
name: 'Tony',
status: 'Absent',
reason: null
},
{
index: 2,
name: 'Chris',
status: 'Present',
reason: null
},
];
datas.map(data=> data.reason ="my reason");
console.log(datas)

How to check if an element exists within an object of arrays

I'm trying to check if an array within an object contains an element userAnswer or not. Is there a good way to do this using es6. I've tried a few however, I can't seem to get it to work properly. Most of my attempts return an error. Any help would be appreciated.
Last Attempt
conductedExam.questions.some(question => question.userAnswer.includes(Object))
Data
{
_id: '1',
questions: [
{ name: '1', userAnswer: 'one' },
{ name: '2', userAnswer: 'two' },
{ name: '2' }
]
};
Use hasOwnProperty:
const conductedExam = {
_id: '1',
questions: [
{ name: '1', userAnswer: 'one' },
{ name: '2', userAnswer: 'two' },
{ name: '2' }
]
};
console.log(conductedExam.questions.some(e => !e.hasOwnProperty("userAnswer")));
Using hasOwnProperty might work.
conductedExam.questions.some(question => question.hasOwnProperty('userAnswer')) returns true

Categories