How do you update a certain nested property in redux state?
Let's say I only want to update the "value" property in the object below. I know you shouldn't deep copy the previous state but how do i only change the property of an object in an array in an object of an array?
Thanks in advance!
market {
shops: [
{
name: 'abc',
items: [
{
name: 'item1',
value: 40,
id: '234rfds32'
},
{}
]
},
{},
{}
]
}
Something like the following:
state = {
...state,
shops: [
...state.shops,
shops[index].items = [
...shops[index].items,
]
]
};
Something like this would work. (code looks ugly, didn't test though)
var shop = state.shops[index];
var items = [...shop.items];
items[<index>].value = 'your value';
shop.items = items;
var shops = [...state.shops];
shops[index] = shop;
state = {
...state,
shops
};
Related
I have the following state:
users: {
'user-0': {
id: 'user-0',
title: 'Bob'
},
'user-1': {
id: 'user-1',
title: 'John'
},
...
I would like to change user-1's id by user-12 for example:
users: {
'user-0': {
id: 'user-0',
title: 'Bob'
},
'user-12': {
id: 'user-12',
title: 'John'
},
...
What is the easiest way to do that with the reducer ?
I was thinking about copying the user-1 data to a new entry by changing the ids, but is there a better way?
Without mutating data:
let data = {
users : {
'user-0': {
id: 'user-0',
title: 'Bob'
},
'user-1': {
id: 'user-1',
title: 'John'
},
'user-2': {
id: 'user-2',
title: 'Bohn'
}
}
}
let dataCopy = {
...data,
'users' :{
...data.users,
'user-12' : {
...data.users['user-1'],
id: 'user-12'
}
}
}
delete dataCopy.users['user-1'];
You need to make a deep copy of your object and only change that copy's properties. Do not mutate the original object. I am using spread operator and delete
Remember this is assuming your users follow the same structure.
First Copy user-1 data and add a new key user-12 and set its value as user-1. then update the id property of user-12 and remove user-1 key from the state.
users["user-12"] = {...users["user-1"], id:"user-12"};
// remove user-1 key from users state
delete users["user-1"]
I am trying to filter the parent array products based on the selected value which should be contained as the child. For example in my case I was trying to get all the product objects as an array which contained the string "iphone". It is not working for me and I can't seem to locate my error. Please may someone help.
What I have tried:
const selected = 'iphone'
const products = [
{
id: "4irnflpd0",
productItem: [ "iphone", "ipad", "kindle"],
},
{
id: "glrscb1m3s9k",
productItem: ["airpods","iphone",],
},
{
id: "uumkugk3jxof",
productItem: ["macbook","cable"]
},
]
var filtered = products.map(o=>{
o = Object.assign({},o); //Clone the object. So any changes will not affect the original array.
o.productItem.map(p=>{ //Use map to loop thru the products
p = p.filter(v=>v === selected); //Filter the products which include selected
});
return o;
})
Expected array output:
const products = [
{
id: "4irnflpd0",
productItem: [ "iphone", "ipad", "kindle"],
},
{
id: "glrscb1m3s9k",
productItem: ["airpods","iphone",],
},
]
Just a simple filter() method should work for us in this case. T further simplify, we can also use object restructuring, so instead of writing product.productItem.includes(selected), we'll only need to write productItem.includes(selected).
All we have to do is filter the source array by which items include the selected value:
const selected = 'iphone';
const products = [
{ id: "4irnflpd0", productItem: ["iphone", "ipad", "kindle"] },
{ id: "glrscb1m3s9k", productItem: ["airpods", "iphone", ] },
{ id: "uumkugk3jxof", productItem: ["macbook", "cable"] },
];
const filtered = products.filter(({productItem}) => productItem.includes(selected));
console.log(filtered);
If you'd prefer not to use Object destructuring, just swap that filter line for this more traditional one:
products.filter(p => p.productItem.includes(selected))
If you're not sure that every single item in your array will have the productItem key, then you should use optional chaining to prevent an error being thrown. This is as simple as adding ? before after property name. Here it is all put together:
products.filter(p => p.productItem?.includes(selected))
First of all no need to make a copy since with map function you allocated the result to new variable without changing the new array
So you need to do this
const filtered = products.map(p=>{
return p.productItem.includes(selected)
})
You can use the filter() methods on products array and find if the selected item is available in the productItems
const selected = 'iphone'
const products = [
{ id: "4irnflpd0", productItem: [ "iphone", "ipad", "kindle"] },
{ id: "glrscb1m3s9k", productItem: ["airpods","iPhone",] },
{id: "uumkugk3jxof", productItem: ["macbook","cable"] }
]
var filtered = products.filter(product =>
product.productItem?.includes(selected));
console.log(filtered);
I have an issue with updating the immutable redux and quite nested data. Here's an example of my data structure and what I want to change. If anyone could show me the pattern of accessing this update using ES6 and spread operator I would be thankful. 😀
const formCanvasInit = {
id: guid(),
fieldRow: [{
id: guid(),
fieldGroup: [
{ type: 'text', inputFocused: true }, // I want to change inputFocused value
{ type: 'text', inputFocused: false },
],
}],
// ...
};
This should do the trick, assuming the data is set up exactly as shown, with the given array indices:
const newData = {
...formCanvasInit,
fieldRow: [{
...formCanvasInit.fieldRow[0],
fieldGroup: [
{ ...formCanvasInit.fieldRow[0].fieldGroup[0], inputFocused: newValue },
...formCanvasInit.fieldRow[0].fieldGroup.slice(1, formCanvasInit.fieldRow[0].fieldGroup.length)
]
}]
};
If index of the element to be changed is to be determined dynamically, you'll need to use functionality such as filter to find and remove the array element you're updating, and then spread the corresponding subarrays by editing the structure of the call to slice.
Try using Immutability Helper
I think in your structure, like this
let news = update(formCanvasInit, {
fieldRow: [{
fieldGroup: [
{ $set: {type: "number", inputFocused: false}}
]
}]
})
I've tried it
Click Me
This is a longer solution but might help you as your redux state grows. I've also changed some of the values in the original state to make a clearer explanation.
const formCanvasInit = {
id: 'AAAAXXXX',
fieldRow: [
{
id: 1001,
fieldGroup: [
{type: 'text1', inputFocused: true}, // I want to change inputFocused value
{type: 'text2', inputFocused: false},
]
},
{
id: 1002,
fieldGroup: [
{type: 'text3', inputFocused: true},
{type: 'text4', inputFocused: true},
]
}
]
};
// the id of the field row to update
const fieldRowID = 1001;
// the value of the field type to update
const fieldTypeValue = 'text1';
const fieldRow = [...formCanvasInit.fieldRow];
// obtain the correct fieldRow object
const targetFieldRowIndex = formCanvasInit.fieldRow.findIndex(fR => fR.id === fieldRowID);
let fieldRowObj = targetFieldRowIndex && formCanvasInit.fieldRow[targetFieldRowIndex];
// obtain that fieldRow object's fieldGroup
const fieldGroup = [...fieldRowObj.fieldGroup];
// obtain the correct object in fieldGroup
const fieldIndex = fieldGroup.findIndex(fG => fG.type === fieldTypeValue);
const fieldToChange = fieldIndex && fieldGroup[fieldIndex];
// replace the old object in selected fieldGroup with the updated one
fieldGroup.splice(fieldIndex, 1, {...fieldToChange, inputFocused: false});
// update the target fieldRow object
fieldRowObj = {...fieldRowObj, fieldGroup};
// replace the old fieldGroup in selected fieldRow with the updated one
fieldRow.splice(targetFieldRowIndex, 1, fieldRowObj);
// create the new formCanvasInit state
const newFormCanvasInit = {...formCanvasInit, fieldRow};
I'm using a nested array with the following structure:
arr[0]["id"] = "example0";
arr[0]["name"] = "name0";
arr[1]["id"] = "example1";
arr[1]["name"] = "name1";
arr[2]["id"] = "example2";
arr[2]["name"] = "name2";
now I'm trying to get a nested Json Object from this array
arr{
{
id: example0,
name: name00,
},
{
id: example1,
name: name01,
},
{
id: example2,
name: name02,
}
}
I tought it would work with JSON.stringify(arr); but it doesen't :(
I would be really happy for a solution.
Thank you!
If you are starting out with an array that looks like this, where each subarray's first element is the id and the second element is the name:
const array = [["example0", "name00"], ["example1", "name01"], ["example2", "name02"]]
You first need to map it to an array of Objects.
const arrayOfObjects = array.map((el) => ({
id: el[0],
name: el[1]
}))
Then you can call JSON.stringify(arrayOfObjects) to get the JSON.
You need to make a valid array:
arr = [
{
id: 'example0',
name: 'name00',
},
{
id: 'example1',
name: 'name01',
},
{
id: 'example2',
name: 'name02',
}
];
console.log(JSON.stringify(arr));
Note that I am assigning the array to a variable here. Also, I use [] to create an array where your original code had {}.
I've got the following array:
This is an array of Users, and each User has an Attributes array.
Now I want to make a new array with users and only their attributes. Like this
users{
0: {
"phone_number",
"email"
}
}
What would be the best way to achieve this?
thanks
If you need Array of users which contains arrays with users attributes, then you can use Array.prototype.map method:
let users = [
{ Attributes: [ { Name: 'phone_number' }, { Name: 'email' } ] },
{ Attributes: [ { Name: 'phone_number1' }, { Name: 'email1' } ] }
];
let result = users.map((user) => user.Attributes.map((attr) => attr.Name));
console.log(result)