exclude already existing items from array in React - javascript

I am facing a challenge. I have 2 tables in firebase that I need to merge into 1 array. The only thing is that items are the same, they have to be removed from the array. So if an item already exists in an array, it should no longer be added to the array. So at the moment I get to see the items twice. Is there a possibility to prevent this? My function looks like this:
fetchItems(){
this.setState({
personalItems:[],
inactiveItems:[],
sprintItems:[],
})
let ref = Firebase.database().ref('/sprints/1/items/');
ref.on('value' , snapshot => {
snapshot.forEach((childSnap) => {
let state = childSnap.val();
console.log('firebase output:'+state)
var newelement = {title: state.title, author: state.author,user: state.user, public: state.public, x: state.x, y: state.y, key: state.key, match: state.match, notes: state.notes, status: state.status};
this.setState(prevState => ({
personalItems: [...prevState.personalItems, newelement],
}));
console.log('firebase'+state.name);
});
})
let refInactive = Firebase.database().ref('/users/'+this.state.user+'/items/');
refInactive.on('value' , snapshot => {
snapshot.forEach((childSnap) => {
let state = childSnap.val();
var newelement = {author: state.author, title: state.postit, status: state.status, key: state.key, user: state.user, match: state.match, x: state.x, y: state.y, public: state.public, notes:state.notes };
this.setState(prevState => ({
personalItems: [...prevState.personalItems, newelement],
}));
});
})
}
My database looks like this:
So you see that these items have the same key. These are also identical to each other. However, if 1 has already been added, this is sufficient, now they are both added.

Here is how you can merge an array into another without duplicates.
for(arr1Element of array1){
if(!array2.some(arr2Element => arr2Element.id === arr1Element.id)){
array2.push(arr1Element)
}
}

You could use a Set, which doesn't let you add duplicate values.
So the easiest you could achieve is something like:
const yourFinalArray = [...new Set([...arr1, ...arr2]);
Hope this helps.

Related

How to flat array in zustand

I have a brands list array, every brand object has a brand name & products
So the first time, I pushed the new brand object to the brands list, and that's work well,
Now if I want to push a new brand to the brands list and keep the previous brand data it does not work as expected.
and it looks like this
the expected should be like this
I'm trying to use flat() but not work here
minimal reproduction here
Code
import create from 'zustand';
import {persist} from 'zustand/middleware';
import {zustandStorage} from '../utils/Storage';
export const useFavoritesStore = create(
persist(
set => ({
brandsFavoritesList: [],
updateFavList: brandData => {
set(state => ({
brandsFavoritesList:
// check if there are any brands on the list before
state.brandsFavoritesList.length > 0
? state.brandsFavoritesList.map(brand =>
// if the brand exists before pushing new products
brand.tenant === brandData?.tenant
? {
...brand,
products: [...brand.products, ...brandData.products],
}
: // if the brand does not exist before push the new brand data to the brandsFavoritesList
// Issue here...
[...state.brandsFavoritesList, brandData].flat(),
)
: [...state.brandsFavoritesList, {...brandData}],
}));
},
}),
{
name: 'favorites-local',
getStorage: () => zustandStorage,
},
),
);
It looks like you want something like
function updateBrandsFavoritesList(brandsFavoritesList, brandData) {
const brandIndex = brandsFavoritesList.findIndex((brand) => brand.tenant === brandData.tenant);
if (brandIndex < 0) {
// This is a new brand, append it to the list.
return [...brandsFavoritesList, brandData];
}
// This is an existing brand, update it.
const existingBrand = brandsFavoritesList[brandIndex];
const updatedBrand = {
...existingBrand,
products: [...existingBrand.products, ...brandData.products],
};
return brandsFavoritesList.map((brand, index) => (index === brandIndex ? updatedBrand : brand));
}
const updateFavList = (brandData) => {
if (!brandData) return;
set(({brandsFavoritesList}) => ({
brandsFavoritesList: updateBrandsFavoritesList(brandsFavoritesList, brandData),
}));
}
– no need for flat.
The complex logic of finding and updating a brand has been moved to a separate free function which should be easier to e.g. test in isolation too.
(Even better still would be to use TypeScript so errors would be more obvious...)

Adding an array and an object to an array react hooks

I'm trying to add an array and an object to an array.
This is my constructor
const [dashboard, setDashboard] = useState({ loading: true, data: [], address: '' })
and this is how I wanted the data to end up
{
loading: true,
data: [{id: 0, name: 'A'}, {id: 1, name: 'B'}],
address: 'xxx'
}
I can't seem to figure it out and was only able to manage to add the arrays but not the other objects like loading and address with something like this but this is not what I need and I'm just giving an example of what I tried doing:
the constructor of this one in the bottom is different from what I want to use, I used something like this
const [dashboard, setDashboard] = useState([])
setDashboard((prev) => {
return [...prev, newData]
})
If I understand your problem correctly you are trying to do something like this:
setDashbaord(prevDashboard => ({ ...prevDashboard, address: "xxx", data: [...prevDashboard.data, newData] }));
Is that what you are looking for?
const [dashboard, setDashboard] = useState({ loading: true, data: [], address: '' })
The line above looks great, no problems there.
setDashboard((prev) => {
return [...prev, newData]
})
Doing this will set your dashboard variable to be an array, and is definitely not what you said you wanted.
setDashboard((prev) => {
return {
...prev,
data: [...prev.data, ...newData] // <-- assuming new data is an array
}
})
Depending on what newData looks like you may need to manually merge the data into your previous data object. For instance, if you want to ensure you have no duplicate values in the array, or you need to sort them.

Not able to set state as array of objects inside map function

I am getting data from word press API then I structure the data inside the map function. I am not able to set state as array of objects inside map function I
get Arrays of different objects or Objects of different objects but not a single
Array of Objects
const rsp = response.data;
const map = rsp && rsp.map(item => {
let struct = {};
let data = [];
const id = item.id;
const title = item.title['rendered'];
const image = item['_embedded']['wp:featuredmedia'][0].source_url;
const banner = item.ACF.banner_image.url;
const products = item.ACF.celebrity_products;
let store={
id:id,
title:title,
image:image,
banner:banner,
products:products
};
setRes(prevState => {
// struct['data'] =store;
// data.push(store);
return{ ...prevState,
id: store.id,
name: store.title,
uri: store.image,
banner: store.banner,
products: store.products
}})
});
I think you'd want more something like :
const [items, setItems] = useState([])
rsp && setItems(rsp.map(item => ({
id: item.id,
name: item.title['rendered'],
uri: item['_embedded']['wp:featuredmedia'][0].source_url,
banner: item.ACF.banner_image.url,
products: item.ACF.celebrity_products
})))
I think you didn't provide the complete story of you code. but I think we can help.
if you intend to have the result of your processing as an array inside the map variable then you should've returned something inside it like
let oddNumber = [ 1, 3, 5 ];
const map = oddNumber.map( oneOddNumber => { return oneOddNumber * 2; } );
// now map is [ 2, 6, 10 ]
or if you intend to save the array you want using setRes function then you should've done something like
setRes(prevState => ({
...prevState,
theResultArray: [...prevState.theResultArray, { id: store.id, ..... } ]
}))
and now you state have the property name theResultArray which is an array of object which you've iterated on.
hope you can provide more complete code so help can be more clear next time :D

Merge array with nested objects if id matches or add to the end

I am trying to assign clone/merge object, that has array where id matches or add to an end:
newState = Object.assign({}, state, {
data: {
newest: {
result: action.payload.result,
list: action.payload.items,
request: action.payload.items
},
itemList: [
...state.data.itemList,
{
id: action.payload.id,
list: action.payload.items,
request: action.payload.items
}
]
}
});
In this case ...state.data.itemList is an array with objects where I want to find an existing object with ID and merge list + request nested objects. However, if there is no object with that ID I want to add it to the list.
Current approach always adds it to the end, which of course is not what I want.
Thanks.
Don't feel pressured into making the new state in one operation. Here would be my implementation. I would check my array for the current id using Array#some. Here are some fun ES6 tricks too.
const newState = {...state}
const {result, items, id, items} = action.payload
const data = {newest: {result, list: items, request: items}}
const hasId = newState.data.itemList.some(item => item.id === id)
if (!hasId) {
newState.data.itemList.push({id, list: items, request: items})
}
return {...newState, data}

JavaScript Matching one array with another?

above i have the picture of my arrays, below code i have mapped 2 sets of array .Purpose of this function is to make '_polygons' empty array. i have a rest service which is 'this.siAsset.updateComponent(_id, _polygons)' that is designed to update each asset. only thing is, i cant seem to pass an array of data to the update component service i have, its designed to take one id and one object as a parameter (if there is a way around , please provide) as you can see by the picture, both _id and _polygons have arrays of id's an arrays of objects. Question is, how can i loop and match to call the rest to go through each id and object instead of calling by writing the code 9 times like this.siAsset.updateComponent(_id[0], _polygons[0]) ...this.siAsset.updateComponent(_id[9], _polygons[9])
deleteAllZones = () => {
let assetVal = this.asset.$$state.value
console.log('tenant', assetVal)
let _polygons = assetVal.map(function (a) {
a.polygon = []
return a
})
console.log('a',_polygons)
let _id = assetVal.map(function (a) {
let id = a.id
return id
})
console.log('id',_id)
let message = this.$filter('translate')('SI-MESSAGES.DELZONE-MSG');
let title = this.$filter('translate')('SUBHEADER.DELZONE-TITLE');
let button = this.$filter('translate')('BUTTON.DELETE');
this.siAlertDialog.confirm(message, title, button)
.then(() => {
this.siAsset.updateComponent(_id, _polygons).then(() => {
this.toastIt.simple(this.$filter('translate')('SI-MESSAGES.ZONE-DELETED'))
}, (err) => {
this.siAlertDialog.error();
}
)
})
}
Your code snippet doesn't work. I've made dummy entries. This should give you an idea. Basically, you need to loop over one array and use the index to find corresponding items in the second
// Mocking data here
let assetVal = [{
id: 1
},
{
id: 2
},
{
id: 3
}
]
let _polygons = assetVal.map(function(a) {
a.polygon = []
return a
})
//console.log('a', _polygons)
let _id = assetVal.map(function(a) {
let id = a.id
return id
})
//console.log('id', _id)
// Mocking done
let updateComponent = (id, polygon) => {
return new Promise((resolve, reject) => {
resolve({
id,
polygon
})
})
}
_id.forEach((id, i) => {
updateComponent(id, _polygons[i]).then(result => {
console.log(result)
})
})
Also, by looking at your code, it doesn't look like your updateComponent method needs id to be passed as a parameter as it is already present in the polygon as well. Maybe you want to refactor that.

Categories

Resources