Add object to existing array in state - reactjs

I have an application that uers lets create new tables, lets say I have the following state:
const initialState = {
table: [{
id: 1,
item: {}
}]
}
Now I want to add new objects to the item:
The reducer:
case types.ADD_ITEM:
return {
...state,
table: [...state.table, { item: action.item}],
loading: false
}
So after user adds new items in a table the state should look something like this:
table: [
// table with id 1
{
id: 1,
item: {
id: '1',
data: 'etc'
}
item: {
id: '2',
data: 'blabla'
}
},
// table with id 2
{
id: 2,
item: {
id: '1'
data: 'etc'
}
},
// etc
]
I think I have my reducer wrongly setup.. the tables are added correctly, but Items not.
Current format is:
table: [
{
id: 1,
item: []
},
{
item: {
id: '1'
}
}
]

I think you are trying to add the contents of action.item to your array. What you're currently doing is adding the contents as a new element. You can use the following to achieve your desired output:
case types.ADD_ITEM:
return {
...state,
table: [...state.table, { ...action.item }],
loading: false
}
Or if you want to get only the id field of the item, and store the item inside a item field:
case types.ADD_ITEM:
return {
...state,
table: [...state.table, { id: action.item.id, item: action.item }],
loading: false
}

Related

How to insert map data to an array of object

I am mapping out item values which is an array
const mappedItems = items.map(item => {
return (
<div key={item.id}>
<h2>{item.name}</h2>
<h2>{item.quantity}</h2>
</div>
)
});
What get outputted is like this:
Fun Mix
1
Potato Chips
5
I am trying to insert the items to my DB from my API, and the structure of the fields is like this:
Items: {
name: //Since the mapped value of the name is an array how can I store all the mapped names in this name field which is an object
quantity: //Same for quantity
},
In my backend controller, I am getting the value like this:
const order = new Order({
Items: req.body.Items,
});
My DB structure where the items are being inserted to is like this
Items: [
{
name: { type: String, required: true },
quantity: { type: Number, default: },
}
]
You could do like this (unless I missunderstood what you are trying to do):
const backendItems = items.map(item => {name:item.name, quantity: item.quantity})
So in the end, backendItems looks like this with your example:
backendItems: [
{
name: "Fun mix",
quantity: 1,
},
{
name: "Potato Chips",
quantity: 5,
}
]

In a one to many relationship, is there a way to filter the parent objects via an attribute of the child?

I have a rails backend with the following relationships: a USER has many MOVES. a Move has many boxes. A Box has many items.
I have page that lists all of the boxes inside of a specific move and this page ALSO lists all of the items for that specific move. I have a search bar on this page that enables you to search for specific items. I am able to filter my items display, however, i cannot figure out how to filter my boxes BY the searching for the name of the items WITHIN them.
I have tried iterating over the array of Box objects, and then iterating over the key within each box that points to its array of items. I am able to get the filtered ITEMS, but I dont know how to translate that back to reflect the BOXES with those items.
For instance, in the console I tried:
var filteredBoxes = boxes.map((box) => {
return box.items.filter((i) => {
return i.name.includes(this.state.searchTerm)
})
})
But it keeps returning items, not the boxes im trying to filter.
This is how the JSON looks when I fetch my boxes. I used a serializer to list the items as well:
{
id: 1,
name: "Bedding",
category: "Bedroom",
move_id: 1,
move: {
id: 1,
name: "Leaving for College",
date: "2019-08-12",
user_id: 1
},
items: [
{
id: 1,
name: "Comforter",
image: "https://www.shopmarriott.com/images/products/v2/lrg/Marriott-down-duvet-comforter-MAR-112_1_lrg.jpg",
box_id: 1
},
{
id: 2,
name: "Throw Pillows",
image: "https://media.kohlsimg.com/is/image/kohls/3427815?wid=500&hei=500&op_sharpen=1",
box_id: 1
}
]
},
{
id: 2,
name: "Random Blankets",
category: "Den",
move_id: 1,
move: {
id: 1,
name: "Leaving for College",
date: "2019-08-12",
user_id: 1
},
items: [
{
id: 3,
name: "Pillows",
image: "https://www.greatsleep.com/on/demandware.static/-/Sites-tbp-master-catalog/default/dw9ff5c1cf/product-images/pillows/nautica/down-alt-pillow-2-pack-na-91644/nautica-down-alternative-pillow-2-pack_91644-icon-2500x2500.jpg",
box_id: 2
},
{
id: 4,
name: "Stuffed Animals",
image: "https://s7d9.scene7.com/is/image/JCPenney/DP0817201617082870M?resmode=sharp2&op_sharpen=1&wid=550&hei=550",
box_id: 2
}
]
},
{
id: 3,
name: "Cleaning Supplies",
category: "Kitchen",
move_id: 1,
move: {
id: 1,
name: "Leaving for College",
date: "2019-08-12",
user_id: 1
},
items: [
{
id: 5,
name: "Pillows",
image: "https://www.greatsleep.com/on/demandware.static/-/Sites-tbp-master-catalog/default/dw9ff5c1cf/product-images/pillows/nautica/down-alt-pillow-2-pack-na-91644/nautica-down-alternative-pillow-2-pack_91644-icon-2500x2500.jpg",
box_id: 3
},
{
id: 6,
name: "Stuffed Animals",
image: "https://s7d9.scene7.com/is/image/JCPenney/DP0817201617082870M?resmode=sharp2&op_sharpen=1&wid=550&hei=550",
box_id: 3
}
]
}
you just have to iterate boxes, and so filter items. Based on these filtered items you may choose to return or not a box to the list.
const data = [{
id:1,
name:"Bedding",
category:"Bedroom",
move_id:1,
move:{
id:1,
name:"Leaving for College",
date:"2019-08-12",
user_id:1
},
items:[
{
id:1,
name:"Comforter",
image:"https://www.shopmarriott.com/images/products/v2/lrg/Marriott-down-duvet-comforter-MAR-112_1_lrg.jpg",
box_id:1
},
{
id:2,
name:"Throw Pillows",
image:"https://media.kohlsimg.com/is/image/kohls/3427815?wid=500&hei=500&op_sharpen=1",
box_id:1
}
]
},
{
id:2,
name:"Random Blankets",
category:"Den",
move_id:1,
move:{
id:1,
name:"Leaving for College",
date:"2019-08-12",
user_id:1
},
items:[
{
id:3,
name:"Pillows",
image:"https://www.greatsleep.com/on/demandware.static/-/Sites-tbp-master-catalog/default/dw9ff5c1cf/product-images/pillows/nautica/down-alt-pillow-2-pack-na-91644/nautica-down-alternative-pillow-2-pack_91644-icon-2500x2500.jpg",
box_id:2
},
{
id:4,
name:"Stuffed Animals",
image:"https://s7d9.scene7.com/is/image/JCPenney/DP0817201617082870M?resmode=sharp2&op_sharpen=1&wid=550&hei=550",
box_id:2
}
]
},
{
id:3,
name:"Cleaning Supplies",
category:"Kitchen",
move_id:1,
move:{
id:1,
name:"Leaving for College",
date:"2019-08-12",
user_id:1
},
items:[
{
id:5,
name:"Pillows",
image:"https://www.greatsleep.com/on/demandware.static/-/Sites-tbp-master-catalog/default/dw9ff5c1cf/product-images/pillows/nautica/down-alt-pillow-2-pack-na-91644/nautica-down-alternative-pillow-2-pack_91644-icon-2500x2500.jpg",
box_id:3
},
{
id:6,
name:"Stuffed Animals",
image:"https://s7d9.scene7.com/is/image/JCPenney/DP0817201617082870M?resmode=sharp2&op_sharpen=1&wid=550&hei=550",
box_id:3
}
]
}];
const searchTerm = "Animals"
// function to filter sub-items
const filterItems = items => items.filter((i) => searchTerm ? i.name.includes(searchTerm) : i.name);
const filteredBoxes = data.map(boxes => {
//filter sub-items
const items = filterItems(boxes.items);
//in case there is any item, return that boxes
if (items.length) {
return Object.assign({}, boxes, { items })
}
// in case there is nothing, return false
return false;
}).filter(Boolean); // filter the boxes list removing the false values
console.log('filteredBoxes', filteredBoxes);

How to update multiple element inside List with ImmutableJS?

Hi I am using immutableJS and I would want to update multiple objects in my array if it has the same id from action.contacts
const initialState = fromJS({
list: [{
id: 1,
loading: false,
}, {
id: 2,
loading: false,
}, {
id: 3,
loading: false,
}]
});
action.contacts = [{
id: 1
}, {
id: 2
}]
I expected when I call state.get('list') it would equal to
list: [{
id: 1,
loading: true,
}, {
id: 2,
loading: true,
}, {
id: 3,
loading: false,
}]
what I have done so far is this:
case UNLOCK_CONTACTS:
const indexesOfRow = state.get('list').findIndex((listItem) => {
return action.contacts.map((contact)=> listItem.get('id') === contact.id)
})
return indexesOfRow.map((index)=> {
state.setIn(['list', index, 'loading'], true);
});
}));
but it's not working out for me, didn't update anything
I created a similar solution in a fiddle http://jsfiddle.net/xxryan1234/djj6u8xL/398/
You are missing the point of immutable.js. The objects are not mutable.
const initialState = Immutable.fromJS({
list: [{
id: 1,
loading: false
}, {
id: 2,
loading: false
}, {
id: 3,
loading: false
}],
});
const contacts = [{
id: 1
}, {
id: 3
}]
let newState = initialState.set( 'list', initialState.get('list').map( (row,index) => {
let contact = contacts.find((item)=>{
return item.id == row.get('id')
})
if (contact){
return row.set('loading', true)
}
return row;
}))
console.log(newState.toJS())
see in the updated fiddle http://jsfiddle.net/djj6u8xL/399/
const newState = initialState.update('list', (oldValue) =>
oldValue.map(item =>
action.contacts.find(act =>
act.get('id') === item.get('id')) !== undefined ?
item.update('loading',(oldVal)=> !oldVal) : item))
console.log(newState.toJS())
notice: you need to turn action.contacts into immutable list of immutable Maps.
case UNLOCK_CONTACTS:
return state.set('list', state.get('list').map((listItem) => {
const matched = _.find(action.contacts, (contact) => listItem.get('id') === contact.id);
if (matched) {
return fromJS({ ...listItem.toJS(), loading: true });
}
return listItem;
}));
So I manage to solve it by mapping the list and then finding if the listItem exists in action.contacts. If it matches I return the matched object with loading: true and if not I return the same object.
I am open to suggestions how can I refactor this solution though, I am quite new to immutable js and I feel there is much more simpler way to solve this but I don't know yet.

Mongoose: Update by pushing an object in an array

This is the model I am working with:
name: {
type: String
},
payment: {
id: {
type: String,
required: true
},
cards: [
{
id: {
type: String
},
is_default: {
type: Boolean,
"default": false
}
}
]
}
I want to add a card to the cards array, for example:
card =
id: "some_token"
is_default: true
I am using the update method to push the card to the array, but it won't add the card to the document. Instead, it creates a new document with only those fields:
{
id: "some_token",
is_default: true,
_id: someId
}
Any idea how I can update the actual document I am targeting instead of creating a new document?
Here's my code (using CoffeeScript):
update_where =
payment:
id: "some_id"
update_push =
$push:
'payment.cards':
id: card_token
is_default: false
Customer.update update_where, update_push, {upsert: true}, (err, results) ->
# Do something with the results
Oh… I just noticed my mistake. The problem was in the where statement.
I was doing:
payment:
id: "some_id"
But the right thing to write is the following:
'payment.id': 'some_id'
And it now works!

Mongoose update and find object in multidimentional array

Im trying to get one of my user`s by the following query:
pokertable.findOne({ _id: gameid }, { "players.$.userid": userid })
but that wont execute. How come?
Im also looking for a way to update the user the same way, is that the same approatch?
Model:
pot_history: {
type: Array
},
players : [
{
userid: {
type: String,
default: 0,
},
username: {
type: String,
default: 'ukjent',
},
last_perform: {
type: Number,
default: 0,
},
cash: {
type: Number,
default: 0,
},
hands_history: {
type: Array,
},
}
],
For find use the query:
pokertable.findOne({ _id: gameid, "players.userid": userid });
And for update the same:
pokertable.update({ _id: gameid, "players.userid": userid }, {"players.$.userid": newUserid});

Resources