Cannot delete property of an object in an array- React,redux-toolkit - reactjs

I have an array, which is from redux-store, contains list of object. I use delete operator to delete some certain property of object in the array in a function, but return an errors "Cannot delete property 'message' of #"
Below as my codes:
const transactionSuccess = (data) => {
notifySuccess("payment success");
console.log("products", products);
for (const item of products) {
delete item.message;
delete item.sizes;
}
const userLocal = JSON.parse(localStorage.getItem("user"));
const { token } = userLocal;
const object = {
products: products,
isPaid: data.paid,
description: "paypal;",
};
postAPICart(object, token, history);
};
console.log('products', products) returns 3 objects in an array

Firstly, I really appreciate andres and phry for trying to help me with that question.
I finally reach out the key problem in my code, it's all about shadow and deep copy
const products = [{item1},{item2}] // an array contains list of object
const copiedProducts = [...products] or const copiedProducts = products.map(item => item) will return SHADOW COPPY of products. Spread operator and map dont actually create new item1 and item2 object. Therefore, if you try to delete or add new property in item1 or item2 of copiedProducts, item1 and 2 in original products also be override, then complier then return an error
I came up with this solution:
const productsCopy = JSON.parse(JSON.stringify(products)); // create a deep copy, all objects are totally separated from original one
Below is a link help me above solution:
https://www.javascripttutorial.net/object/3-ways-to-copy-objects-in-javascript/#:~:text=A%20deep%20copying%20means%20that,connected%20to%20the%20original%20variable.
Happy coding day guys

You cannot change values in your store outside of a reducer. And now you may say "hey, this is not a store value", but it most likely is just a reference to the store - and changing any of your products here would in turn also change the store.
You can do something like this:
const newProducts = products.map(({ message, sizes, ...rest }) => rest)
this will leave the original objects alone and create an array of new objects with everything except messages and size for you to work with

Related

Firestore navigation for onUpdate and shuffle an array

I have this Firebase structure:
Firebase Structure.
Then I have a function in my Code, which adds a map called "set".
My Structure is looking like this after: New structure.
Now i want an onUpdate Firebase function, which is called after the map "set" is added in any document.
This function should shuffle my "question" array.
I tried something like this:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}/set/questions')
.onUpdate((change, context) => {
const data = change.after.data();
const previousData = change.before.data();
if (data.name == previousData.name) {
return null;
}
//shuffle code here
});
But Im not sure if .document('duell/{duell_id}/set/questions') is the correct way to navigate to the question array. And at the beginning the "set" is not even existing as explained at the top.
How do I navigate to the question array correctly, that I can pull it & update it shuffled?
You should pass a document path to functions.firestore.document(). You cannot pass a field name, since Firestore Cloud Functions are triggered by documents events.
So you should do as follows:
exports.shuffleSet = functions.firestore
.document('duell/{duell_id}')
.onUpdate((change, context) => {
if (!change.after.data().shuffledSet) {
const data = change.after.data();
const question = data.set.question; // get the value of the question field
const shuffledSet = shuffle(question); // generate the new, suffled set. It’s up to you to write this function
return change.after.ref.update({shuffledSet});
} else {
return null; // Nothing to do, the shuffled field is already calculated
}
});

React Native: update an Array inside an Object

i currently have an object and inside this object i have multiple objects and Arrays. I want replace an Array inside this object with a new Array, so i thought of making a copy of the entire object and simple replace the Array i wan to change with the updated Array. My problem is i couldnt complete my code, i have the idea of how to do it but cant execute it.
setListings(listings=>
listings.map(item =>{
if(item.id === msg.id){
//console.log(item)
//console.log(item.Message)
const newMessages = [msg,...item.Messages]
//console.log(newMessages)
return console.log([msg,...item.Messages],{...item}) // just for testing purpose i
am returning a console log
to see what it will get me. Not correct.
}
return item;
})
);
So basically listings is my state variable, here console.log(item) prints out the entire object, console.log(item.Messages) prints out the current Messages Array which i want to replace, console.log(newMessages) prints out the new Messages Array which i want to replace the current Messages array with.
cartItem.map((food,index)=> {
if(food.food_id == newFoodItem.food_id && food.id == newFoodItem.id){
const AllFoodData = cartItem
AllFoodData[index] = newFoodItem
AsyncStorage.setItem('#Add_cart_Item', JSON.stringify(AllFoodData))
.then(() => {})
.catch(err => console.log(err))
ToastAndroid.showWithGravityAndOffset('Cart Replace Successfully',ToastAndroid.LONG,ToastAndroid.BOTTOM,25,50 )
}
})
So basically what i want to achieve here is to add the msg object to the existing Messages Array.
Since lsitings is an Array of objects using the .map i can spread through each object and check if the id of that object is each to my msg.id. if that is true then i want to return a copy the that specific listing and edit the Messages Array within [msg, ...item.Messages] otherwise return the existing item.
setListings(listings=> listings.map(item => {
if(item.id === msg.id) {
return {
...item,
Messages: [msg, ...item.Messages]
}
}
return item;
}));
});

How to sort how you want the the data from firestore

I have a firestore with lessons, see the picture below, I get from the firestore the title property from each object and display it in the browser, but everytime I refresh the website the lessons are sorted by how they want, why is that happening? I want to sort them how I want, I want to start with 'Introduction' and so on, how can I do that? I think the orderBy() is not working here.
As you see in the image above, the order in the firestore is alphabetical, but in my page is sorted by its own, see the picture below.
I want the result to be by in a specific order, for example we have the following titles, these titles are from the firestore: "Display", "Introduction", "Alignment", my problem is that these 3 titles are in a new order every time I refresh the website, I want them to be: "Introduction", "Alignment", "Display". In my case I have more titles but this is what's happening, I don't know how to align them how I want or even alphabetical if is possible.
Below is the code that I used to get the data from firestore:
useEffect(() => {
db.collection("users")
.doc(`${user.uid}`)
.get()
.then((doc) => {
const allData = { ...doc.data(), id: doc.id };
const intoArray = Object.entries(allData);
intoArray.sort(); // I used sort here because I had the same problem
// (every time a new order) with the
// data when I converted it to an array
const getCSSLessons = intoArray[0][1];
const cssData = Object.values(getCSSLessons);
setCss(cssData);
const getHTMLLessons = intoArray[1][1];
const htmlData = Object.values(getHTMLLessons);
setHtml(htmlData);
const getResLessons = intoArray[3][1];
const resData = Object.values(getResLessons);
setRes(resData);
})
.catch((error) => console.log(error));
}, [user]);
I tried using sort(), for a variable (htmlData) but its not working.
Also, I use map() to display them, if this helps you to answer to my question.
If you use sort without any argument, it will sort array elements alphabetically. It looks like your array elements are arrays, which will end with unexpected behaviors. Use sort argument to ensure it uses your own sorting rules. For example:
const intoArray = Object
.entries(allData)
// I don't know what should be the sorting algorithm
// As an example, I consider each element (`a` and `b`) to
// be arrays and compare both first element as a Number
.sort( (a, b) => a[0] - b[0])
Edit
A more secure way to find elements in an array is to use find:
const getCSSLessons = intoArray[0]
.find( element => element.name === 'CSS Lessons');
I was doing something unnecessary as you see in the first picture I had a main object css and in that object I had sub-objects like alignment and in the sub object I had the properties that I want to display, that sub object was unncessary, istead of sub objects with a pre defined name, I let the firebase to count the sub objects and add as a name a number and the order is the same as I wanted to be.
The code that I used to add data to firebase:
fire
.auth()
.createUserWithEmailAndPassword(email, password)
.then((cred) => {
return db
.collection("users")
.doc(cred.user.uid)
.set({
css: [
{
title: "Introduction",
path: "/css3/introduction",
},
{
title: "Priority",
path: "/css3/priority",
},
],
});

ES6 Add new elements to an array in state

createNewList = (id, input) => {
const foundCard = {...this.state.cards.find(card => id === card.id)};
this.setState(foundCard.list = [...foundCard.list, input]);
};
Hello everyone
There is an array of data (list), which is stored in the state for each object (card).
Problem: I can’t seem to add a new element to this array.
The way it is set up creates only one element and change it every time. But I need to create a new one every time. I tried to create a separate array, add to it using newArray.push (input) and then do this.setState (foundCard.list = [... foundCard.list, ... newArray])`, but have the same result.
I don’t use Redux, because I just started to learn React and I store everything in state yet.
Thanks in advance for your reply.
createNewList = (id, input) => {
const newCards = this.state.cards.map(card => {
if (card.id === id) card.list = [...card.list, input];
return card;
});
this.setState({
cards: newCards
});
};

Array.filter() in Angular 2 Component

In one component I can filter my array using the following:
// Array of product objects
const result = products.filter(p => p.name.includes('val'));
and value of products remains same as the first value but filtered value stores in result.
But in the following code, filter() filters array of strings itself:
// Array of strings
const result = strs.filter(s => s.includes('val'));
The question is how can I filter strings and return result without modifying the strs itself?
Note: I tried with array.filter(function() { return res; }); but didn't make any change.
It returns the filtered ones and don't change the actual array. You are doing something wrong
const strs = ['valval', 'bal', 'gal', 'dalval'];
const result = strs.filter(s => s.includes('val'));
console.log(strs);
console.log(result);
First thing we need to know is, if we filter our list we loose our original data
products: any[] = [
{
"productId": 1,
"productName": "foo-bar",
"price": 32.99
}
]
and can't get it back without re-getting the data from it's source so we have to make another list to store the filtered list.
filteredProduce: any[];
Next if you are working to show a list of filtered product on a grid or something like this we need a way to know when the user changes the filter criteria. we could use event binding and watch for key presses or value changes, but an easier way is to change our _listFilter property into a getter and setter, like this
get listFilter: string {
return this._listFilter;
}
set listFilter(value:string) {
this._listFilter= value;
}
next we want to set our filteredProducts array to the filtered list of products like this
set listFilter(value:string) {
this._listFilter= value;
this.filteredProducts = this._listFilter? this.performFilter(this._listFilter) : this.products;
}
in preceding code we are using js conditional operator to handle the posibility that _listFilterstring is empty, null or undefined.
Next we use this.performFilter(this._listFilter) to filter our list.
performFilter(filterBy: string): any[] {
filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product: any) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
Finally we should assign the main list of products to the filteredProducts and _listFilter to what we want.
constructor() {
this.filteredProducts = this.products;
this._listFilter= 'foo-bar';
}
last step is to change our template to bind to our filteredProducts property.

Resources