Remove object from array in some conditions - javascript

I need to update the filters in order of some situations.
while in some data conditions I need to remove 1 item from an array.
Here is the code
useEffect(() => {
let canceled = false;
const filters = [
new CheckFilterBuilder('badges', 'Badges'),
new CategoryFilterBuilder('category', 'Categories'),
new RangeFilterBuilder('price', 'Price'),
new CheckFilterBuilder('brand', 'Brand'),
];
console.log(filters);
dispatch({ type: 'FETCH_PRODUCTS_LIST' });
shopApi.getProductsList(
state.options,
{ ...state.filters, category: categorySlug }, filters,
).then((productsList) => {
if (canceled) {
return;
}
dispatch({ type: 'FETCH_PRODUCTS_LIST_SUCCESS', productsList });
});
return () => {
canceled = true;
};
}, [dispatch, categorySlug, state.options, state.filters]);
I tried a solution with if() statement but I couldn't put it in the remove item I want is
new RangeFilterBuilder('price', 'Price'),
since it does not accept if() or anything else I couldn't do it.

You could do that by creating a filter that's empty (or has known filters already included) and add (push) additional ones based on the condition
const filters = [new CheckFilterBuilder('badges', 'Badges')];
if (condition === true) {filters.push(new CategoryFilterBuilder('category', 'Categories'))}
if (condition === true) {filters.push(new RangeFilterBuilder('price', 'Price'))}
if (condition === true) {filters.push(new CheckFilterBuilder('brand', 'Brand'))}

you could slice it out of there?
const slicer = (arr, index) => {
if (index === 0) { arr = [...arr.slice(1)]; }
else { arr = [...arr.slice(0, index),...arr.slice(index + 1)]; }
return arr; //or not. I think arrays pass by reference anyway
}

Related

Push object in array when checkbox is checked and remove object when checkbox is unchecked in ReactJS

I am trying to implement a functionality where I want to push object into an array when the user checked it and remove it if the user unselects it. I have a menu where I am collecting user choices. I have implemented code but it has not resolved my issue, Could someone please help me how to resolve this issue. Thanks
const selectSingle = (id, item, index) => {
const user = Cookies.get("user") && JSON.parse(Cookies.get("user"));
let callScheduleIds = Object.assign([], allCallNotifications);
if (callScheduleIds.findIndex((item) => item.order_id === id)) {
callScheduleIds.push({
order_id: id,
phone_number: item.phone1,
sender_id: user.user.id,
});
} else {
callScheduleIds.splice(callScheduleIds.indexOf(id), 1);
}
setAllCallNotifications(callScheduleIds);
};
You can do it by using Lodash.
const selectSingle = (rowIndex, item) => {
let callIds = Object.assign([], allCallNotifications)
if (_.findIndex(callIds, { id: item.id }) === -1) {
callIds.push(item)
} else {
callIds.splice(_.findIndex(callIds, { id: item.id }), 1)
}
setAllCallNotifications(callIds)
}

Functional JavaScript, function returns bool on condition mapping array

I need to push to the array cities if there is no such a city
getCityList() {
const { StoreInfo } = this.props;
this.emptyCityList();
return StoreInfo.map((StoreInfo, index) => {
console.log(this.cityPushCheck(StoreInfo.city));
if (this.cityPushCheck(StoreInfo.city)) {
CITY_LIST.push({
id: index, label: StoreInfo.city, value: StoreInfo.city, disabled: false
});
}
});
}
cityPushCheck(city) {
const MAP = CITY_LIST.map((CITY_LIST) => {
if (CITY_LIST.label === city) {
console.log('are equal');
return false;
}
});
return true;
}
I was trying return CITY_LIST.map((CITY_LIST) =>
without const or return CITY_LITS.map is not working
can't get it.
what I am doing wrong?
[UPDATE]
So this solution worked for me
getCityList() {
const { StoreInfo } = this.props;
this.emptyCityList();
return StoreInfo.map((StoreInfo, index) => {
if (this.cityPushCheck(StoreInfo.city)) {
CITY_LIST.push({
id: index, label: StoreInfo.city, value: StoreInfo.city, disabled: false
});
}
});
}
cityPushCheck(cityLabel) {
const cityFromList = CITY_LIST.find(city => city.label === cityLabel);
return cityFromList === undefined;
}
thanks to #quittle
It's a bit unclear what you are asking for exactly but I believe your question is how to implement cityPushCheck so that it returns false if the city is in CITY_LIST and true otherwise. Assuming CITY_LIST is an Array, there's a helpful function called find on arrays that greedily check for the presence of an entry based on a condition.
cityPushCheck(cityLabel) {
// Grabs the instance of the city from the list if it was present
const cityFromList = CITY_LIST.find(city => city.label === cityLabel);
// cityFromList will be undefined if "find" didn't have a match
return cityFromList === undefined;
}
While use map, you go city by city in your array, and for each return boolean. You might consider use filter, and then check if the filtered array have any length just once
cityPushCheck(city) {
CITY_LIST.filter(CITY => CITY.label == city).length
}
Now, if there isn't such city at array, length is 0 what is equal to false at JS

reactJs setState change property on object within an array

I'm a little bit stuck. I try to override a certain object from an array with another object from another array :
onStepsLayoutChange = (layout) => {
console.log("The new layout is", layout); //Array
this.setState((prevState) => ({
layout: layout,
stepsData: prevState.stepsData.map(step => {
layout.map(l => {
if(step.identifier === parseInt(l.i)){
console.log("Match", l, step); // "l" is not empty and actually matches only if "id" is identical
return {
...step,
layout: l //I want to override "layout" with the current layout "l"
}
}
});
return step
})
}), () => console.log("LayoutChange:", this.state.layout, this.state.stepsData)); // "layout" in each step is empty
};
Whats my fail in this case?
Issue is, you are missing the default behaviour of #array.map. For each array value map will return some value by default undefined. You are running map inside map, So the final value that stepData will have is:
[[...], [...], [....] ....]
Instead of using nested map, use #array.findIndex or #array.find and return the value.
Write it like this:
stepsData: prevState.stepsData.map(step => {
let index;
index = layout.findIndex(l => step.identifier === parseInt(l.i));
if(index >= 0){
return {
...step,
layout: layout[index]
}
}
return step;
})
Check this snippet:
let a = [1,2,3,4,5];
let b = [2,3];
let result = a.map(i => {
return b.map(j => {
if(i === j)
return 0;
})
return i;
})
console.log(result);
If you stepsData must be an array of arrays you forget one return:
onStepsLayoutChange = (layout) => {
console.log("The new layout is", layout); //Array
this.setState((prevState) => ({
layout: layout,
stepsData: prevState.stepsData.map(step => {
return layout.map(l => { //here <---
if(step.identifier === parseInt(l.i)){
console.log("Match", l, step); // "l" is not empty and actually matches only if "id" is identical
return {
...step,
layout: l //I want to override "layout" with the current layout "l"
}
}
});
return step
})
}), () => console.log("LayoutChange:", this.state.layout, this.state.stepsData)); // "layout" in each step is empty
};

How to check if there is an item in an array that exists in another array?

I have the following React code that I want to use to disable a button:
todos.filter(todo => todo.completed === true)
.map(todo => todo.id)
.includes(this.state.checkedIds)
My problem is it always returns false. I want to compare two arrays here. If there is an item present in both arrays of this.state.checkedIds and todo.ids it should return true or else false.
Make checkedIds into a set and then compare them.
var checkedIds = new Set(this.state.checkedIds)
todos.filter( todo => todo.completed === true )
.map( todo => todo.id )
.filter( id => checkedIds.has(id) )
You can boil it down even further to the following, assuming todo.completed returns a boolean.
Of course, replace the checkedIds with this.state.checkedIds.
const todos = [
{ id: 1, completed: true },
{ id: 2, completed: false },
{ id: 3, completed: true },
{ id: 4, completed: false }
];
const checkedIds = [1, 2, 4, 5];
const results = todos
.filter(todo => todo.completed)
.map(todo => checkedIds.includes(todo.id));
console.log(results);
You can use include in combination with some for succinctness
var arr1=[1,2,3,4,5,6,7];
var arr2=[8,9,10];
var arr3=[2,1,3,4,5,6,7];
if(arr1.some((x)=> arr2.includes(x))){
console.log('true');
//do something
}else{
console.log(false);
//do something
};
if(arr1.some((x)=> arr3.includes(x))){
console.log('true');
//do something
}else{
console.log(false);
//do something
};
// something even shorter would be
arr1.some((x)=> arr2.includes(x))?console.log(true):console.log(false)
You can just use a simple loop for this:
function arraysIntersect(arr1, arr2) {
for (var i = 0; i < arr1.length; ++i) {
if (arr2.includes(arr1[i])) return true;
}
return false;
}
I assume state.checkedIds is an array. If that's true, your code doesn't work because you are checking whether your filtered and mapped todos include checkedIds (which it doesn't) instead of checking whether it includes any of the elements of the array checkedIds (which it might).
You can use my code like this:
var doneTodoIds = todos.filter(todo => todo.completed === true ).map( todo => todo.id).includes(this.state.checkedIds);
var result = arraysIntersect(doneTodoIds, this.state.checkedIds);
You could also solve this with a higher level data structure (Alejandro's suggestion), but that might not be necessary (depending on the context of your code fragment).

Chaining Immutable.js methods with deeply nested Maps/Lists

I have an Immutable.js collection that looks like this:
{ groups: Immutable.Map({
{
id: 1,
members: Immutable.List
},{
id: 2,
members: Immutable.List
}
})
}
I'm getting an updated members array and the group id from my server. How can I find the correct group by id and then update the members prop and then return a new groups collection?
I have something like this so far that doesn't work.
return state.update('groups', groups => {
for (let group of groups) {
if (group.id === action.id) {
group.members = Immutable.fromJS(action.members);
// not sure what I would do with updated here
//const updated = group.members.set('members', action.members);
}
}
return groups;
};
Also, tried this and it doesn't seem to complete, because the console.log never fires.
let update = state.get('groups')
.find(group => group.id === action.id)
.set('members', action.members)
console.log(update) // nothing, no error either
The following works, but there has to be a better, more elegant way than using fromJS and then toJS.
return state.update('groups', groupsImmutable => {
const groups = groupsImmutable.toJS();
for (let group of groups) {
if (group.id === activeId) {
group.members = action.members;
break;
}
}
return Immutable.fromJS(groups);
});
thanks!
This would work:
return state.update('groups', groups => {
return groups.map(group => {
if (group.get('id') === action.id) {
return group.set('members', Immutable.fromJS(action.members))
} else {
return group
}
})
})
You could also use findIndex to get the index of the matching group id and then use setIn to update the members array:
const updateIndex = state.get('groups').findIndex(group => group.get('id') === action.id);
if (updateIndex === -1) { // action.id not found
return state;
} else {
return state.setIn(['groups',updateIndex,'members'], Immutable.fromJS(action.members))
}
Your examples failed because you were trying to directly modify a child element, that's not how Immutable works. You need to update the entire state object with the new element.

Categories