I have a state object with a category array in it. In this array of objects, one of the keys ("list") of the object is assigned an array.
What I need to do is
filter a specific object in the category array by name
add a new object to the "list" property (array) of the filtered object (keeping the old ones)
Example
const initialState = {
category: [
{
name: "new",
color: "#5236C1",
list: [
{
title: "name title",
about: "about",
imgLink: 'https://www.google.com/s2/favicons?domain=https://mail.yandex.ru/',
url: 'https://www.yandex.ru'
},
// there should be a new object
]
},
tried to do so
const addBM = (state, payload) => {
console.log(payload)
const {url, title, about, cat} = payload
let selectCatArr = state.category.filter((item) => item.name == cat)
return {
...state,
category: [...state.category, {list: [title, url, about ]}]
}
}
there should be a new object
I have modifed the addBM function and added some comments which explain the code.
const addBM = (state, payload) => {
console.log(payload)
const {url, title, about, cat} = payload
// use map method instead of filter
const modifiedCategory = state.category.map(categoryItem => {
// only modify the category item if it's name matches the cat argument
// otherwise return the original category item
if (categoryItem.name == cat) {
// create a copy of the category item object
let modifiedCategoryItem = {
...categoryItem,
// modify the list array of this object by
// creating a copy of the array and
// adding a new object with (url, title and about arguments) in this array
list: [...categoryItem.list, {url, title, about}]
};
return modifiedCategoryItem;
} else {
return categoryItem;
}
});
return {
...state,
category: modifiedCategory
}
};
Related
How can I filter a list (array with objects) with a filter list (array) and find intersections? I add to the filter array every time a user checks the checkbox clicking on particular filter. When user unchecks the checkbox I remove from filter array. Somehow whateever i try doing, i always return the entire reviews array including ALL not filtered items. Why? Thanks!!
const reviews = [
{
title: "item 1",
filter_results: {
features: ["message", "call"],
pricing: ["Business", "Free", "Whatever"],
rating: [1]
}
},
{
title: "item 2",
filter_results: {
features: ["call", "copy", "paste"],
pricing: ["Business"],
rating: [1]
}
},
{
title: "item 3",
filter_results: {
features: ["copy", "connect", "wifi"],
pricing: ["Free",
rating: [2]
}
}
]
const filteredReviews = {
pricing_options: ["Business"],
popular_features: ["copy, call"],
rating: [1, 2]
}
const update = (reviews, categoryName) => {
if (categoryName) {
return reviews.filter(review => {
return review.filter_results[categoryName].filter(value => {
if (filteredReviews[categoryName].includes(value)) {
return review
}
})
})
} else {
return reviews
}
}
update(reviews, "pricing")
Return a boolean on filter callback, and do a better filtering mechanism:
const update = (reviews, filters) => {
if (filters) {
return reviews.filter(review =>
Object.entries(filters)
// Change to `some` if the filters are OR'ed instead of AND'ed
.every(
([filter_key, filter_values]) =>
// Change `some` to `every` if all elements in the
// userFilter[*] array MUST be matched instead of some of them
filter_values.some( (filter_value) =>
review.filter_results[filter_key]
.includes(filter_value)
)
)
)
} else {
return reviews
}
}
// Fix variables names:
// - `userFilters` contains the filters selected by the user
// - `filteredReviews` contains the array of reviews, resulting from
// filtering the reviews using the `userFilters`
// Fix key names: Use same keys than in reviews, instead of:
// - `pricing_options` => `pricing`
// - `popular_features` => `features`
const userFilters = {
pricing: ["Business"],
// Transformed/fixed to 2 values. Was it a typo?
features: ["copy", "call"],
};
const filteredReviews = update(reviews, userFilters);
Filter callback function should return a "boolean", you are returning arrays which evaluate always to "true".
In my post request I need to pass an array with an object inside it.
when I tried to add new properties inside an object its adding.
but when I tried to add when an object is present inside an array its not adding.
I have sportsvalues as array const sportsValues = [{ ...values }];
I am trying to build something like this, so that I can pass in the api
[
{
"playerName": 3,
"playerHeight": 1
}
]
can you tell me how to fix it.
providing my code snippet below.
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
console.log("sportsValues--->", sportsValues);
// sportsValues.playerName = 3//'';
// sportsValues.playerHeight = 1//'';
console.log("after addition sportsValues--->", sportsValues);
console.log("after deletion sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}
Since sportsValues is an array of objects, you can push new object into it. Check out code below.
const sportsValues = [];
sportsValues.push({
playerName:'3',
playerHeight: 1,
});
console.log(sportsValues);
I don't fully understand what you're trying to do, but here's some pointers:
If you're trying to update the object that's inside the array, you first have to select the object inside the array, then update it's attribute:
sportsValues[0].playerName = 3
although, I recommend building the object correctly first, then passing it to the array, it makes it a little easier to understand in my opinion:
const sportsValues = [];
const firstValue = { ...values };
firstValue.playerName = '3';
sportsValues.push(firstValue);
or
const firstValue = { ...values };
firstValue.playerName = '3';
const sportsValues = [firstValue];
or
const sportsValues = [{
...values,
playername: '3',
}];
if you're trying to add a new object to the array, you can do this:
const sportsValues = [{ ...values }];
sportsValues.push({ playerName: '3' });
etc...
Array.push adds a new item to the array, so in your code, you're going to have 2 items because you assign 1 item at the beginning and then push a new item:
const ar = [];
// []
ar.push('item');
// ['item']
ar.push({ text: 'item 2' });
// ['item', { text: 'item 2' }]
etc...
export function sports(values) {
const sportsValues = [{ ...values }];
sportsValues.push(playerName:'3');
let playerName='3'
sportsValues.playerName= playerName; // you can bind in this way
console.log("sportsValues--->", sportsValues);
return dispatch => {
axios
.post(`${url}/sport`, sportsValues)
.then(() => {
return;
})
.catch(error => {
alert(`Error\n${error}`);
});
};
}
There is a function that adds objects product to products in state
addProductToCart(productId, productName)
{
var product = {
id: productId,
name: productName,
};
this.setState({
products: {
...this.state.products,
[product.id]: product
}
});
}
but these objects are sorted by [product.id]. How do I sort them in the order they are added to the cart?
maintain one more array ids in which, you can append the productIds as they are added :
addProductToCart(productId, productName)
{
var product = {
id: productId,
name: productName,
};
this.setState({
products: {
...this.state.products,
[product.id]: product
},
productIds : [...ids, product.id]
});
}
You can then iterate over the array to retrieve the product in the order of their insertion.
If you read this objects are by default key value pairs,
You have 2 options you can use #Easwar solution or you can use array instead to store.
As far as I see your strucutre there is nothing wrong in using the array structure for your requirement.
You should restructure your state like this
constructor() {
super();
this.addProductToCart = this.addProductToCart.bind(this);
this.state = {
products: []
};
}
addProductToCart() {
productsId--;
var product = {
id: productsId,
name: 'test',
};
this.setState({
products: [...this.state.products,product]
});
}
Demo
As I can see you have a problem getting removed object from array you can use this easily
removefromCart(value) {
var array = [...this.state.products]; // make a separate copy of the array
var index = array.findIndex(a => a.id === value);
if (index !== -1) {
array.splice(index, 1);
this.setState({ products: array });
}
}
I'm working on a table planner app where guests can be assigned to dinner tables.
I have created an object array in the state called tabledata, which will contain objects like so:
this.state = {
tabledata: [
{
name: "Top Table",
guests: ["guest1", "guest2", "guest3"]
},
{
name: "Table One",
guests: ["guest3", "guest4", "guest5"]
}
]
}
I am then creating a drag and drop interface where guests can move between tables. I have attempted to update the state like so:
updateTableList (tablename, guest) {
const selectedTableObj = this.state.tabledata.filter((tableObj) => tableObj.name === tablename);
const otherTableObjs = this.state.tabledata.filter((tableObj) => tableObj.name !== tablename);
selectedTableObj[0].guests.push(guest);
const updatedObjectArray = [...otherTableObjs, selectedTableObj];
this.setState({
tabledata: [...otherTableObjs, ...selectedTableObj]
});
}
This works but because I am removing selectedTableObj from the state and then adding it to the end of the array I'm getting some funky results on screen. The updated table always goes to the bottom of the page (as you'd expect).
How can I update the object without changing its position within the array?
Find the index of the table you want to update using Array.findIndex(). Create a new tabledata array. Use Array.slice() to get the items before and after the updated table, and spread them into the new tabledata array. Create a new table object using object spread, add the updated guests array, and add the table object between the previous items:
Code (not tested):
updateTableList(tablename, guest) {
this.setState((prevState) => {
const tableData = prevState.tabledata;
const selectedTableIndex = tableData.findIndex((tableObj) => tableObj.name === tablename);
const updatedTable = tableData[selectedTableIndex];
return {
tabledata: [
...prevState.tabledata.slice(0, selectedTableIndex),
{
...updatedTable,
guests: [...updatedTable.guests, guest]
},
...prevState.tabledata.slice(selectedTableIndex + 1)
]
};
});
}
selectedTableObj[0].guests.push(guest) directly mutates the state which is not encouraged in React.
Try this:
this.setState((prevState) => {
const newData = [...prevState.tabledata];
// if you pass in `index` as argument instead of `tablename` then this will not be needed
const index = prevState.tabledata.findIndex(table => tableObj.name === tablename);
newData[index] = {
...newData[index],
guests: newData[index].guests.concat([guest]),
};
return { tabledata: newData };
});
You also did not remove the guest from its previous table so you need to modify for that.
You can do it with a Array.reduce
let newState = this.state
// let newState = {...this.state} // in case you want everything immutable
newState.tableData = newState.tableData.reduce((acc, table) =>
if(table.name === tableName) {
return acc.concat({...table, guests: table.guests.concat(newGuest)})
} else {
return acc.concat(table)
}
)
I have attributes of objects of an array that I would like to store in an array. Below is my data.
What I want to do achieve is to store displays name attribute in opt[] so it would look like this opt = ['info1', 'info2', 'info3', ... ]
getEditData (id) {
axios.get('/api/campaign/getEdit/' + id)
.then(response =>{
this.campaign = response.data.campaign;
})
.catch(e=>{
console.log(e.data);
this.error = e.data
})
}
Above snippet is the source of the campaign object
You can use this expression:
campaigns.displays.map( ({name}) => name );
const campaigns = { displays: [{ name: 'info1'}, { name: 'info2'}] };
const result = campaigns.displays.map( ({name}) => name );
console.log(result);
This will display an array containing the property names of each object in the displays array
var data = {
displays: [
{
capacity: 9000,
id: 1,
imei: 44596
}
]
};
data.displays.forEach(function(obj, idx) {
console.log(Object.keys(obj));
});
Object.keys() is what you need