How to store Object in Cookies - javascript

I have an app in Nuxt and I would like to store content of the shopping cart in the cookies. To store cookies I use cookie-universal-nuxt package. However, I am not able to store "some" objects in it. Here is an example:
const userInfo = {
name: 'Smith',
age: 41,
isVip: true,
}
this.$cookies.set('userInfo', JSON.stringify(userInfo))
console.log(this.$cookies.get('userInfo'))
This works as it should, no problem there.
Problem is, it does not work with my real objects:
const savedProductsArray = this.$store.getters['cart/products'] // returns array of products
const savedProducts = savedProductsArray[0] // select first one
this.$cookies.set('productInfo', JSON.stringify(savedProducts))
console.log(this.$cookies.get('productInfo')) // prints undefined
So the second object is apperently not stored in cookies. Any idea why? Thanks!
Btw, this is how userInfo object looks like in console:
Object {
age: 41,
name: "Smith",
isVip: true,
}
and savedProducts:
Object {
calories: 123,
name: "a",
...
}
So it looks like they are the "same" objects, but somehow only the first one can be stored in cookies...

Update: OP confirmed the issue was with cookie size.
There could be multiple issues, could you check what is the value of JSON.stringify(savedProducts) also it will help if you could include fully stringified savedProducts in the post.
Also, be aware per domain only about 4KB is allowed size for cookie so if you are trying to store that much data that could be the reason as well

Related

Retrieve the value of a List/Map the proper way with Immutable JS in TypeScript

I've been working with Immutable JS for a few months. And I really like the functionality it gives. But I've been doing something I don't like over and over again. It has to do with retrieving a value from either a List or Map.
When retrieving this value, I fist check if it even exist, when I it does, I want to interact with it further. But up until this day, I still don't know how to do this "the proper way".
I know what I'm writing could be much better because I've seen the functionalities (like fold) within a Functional Framework like fp-ts. And so I know there must be a nicer way of retrieving a value from a List/Map.
Does anyone know how?
I will add some code examples below and also a link to the source code:
Playground
import { Map, List } from 'immutable'
import { pipe } from 'fp-ts/function'
import { fold } from 'fp-ts/boolean'
// Example 1 - with Map
type Person = {
name: string
surname: string
age: number
}
const persons = Map<number, Person>()
.set(1, {name: 'Jack', surname: 'Bright', age: 25})
.set(2, {name: 'Jane', surname: 'Bright', age: 22})
.set(3, {name: 'Mike', surname: 'Bright', age: 21})
const someProgram = (id: number = 2) => {
// ... Does some things
// We need to update a user with id: 2
if (persons.has(id)) {
// This is where the problem is. We know that the person exists, because we're in the true clause. But still we get undefined as possible value.
const person1 = persons.get(id) // Person | undefined
// Now we add the ! and it works, but this is not nice nor elegant. What is the proper way of doing this (getting an element)?
const person2 = persons.get(id)! // Person
} else {
console.log('Error')
}
}
// Example 2 - With fp-ts & List
/**
* I use fp-ts a lot lately, and even with this I get this ugly way of adding the ! at every retrieval.
* An example with List<Person>. We want to get the first Person in the list if the list isn't empty.
*/
pipe(persons.isEmpty(), fold(
// onFalse
() => console.log('Error'),
// onTrue
() => {
// We know that there is a user in this clause. But how do we get it properly?
const person1 = persons.get(0) // Person | undefined
const person2 = persons.get(0)! // Person
}
))
This sounds like a unsolved issue of TS. It's not directly related to ImmutableJS, more a generic problem with nullable getter functions in TS.
You could rewrite the code by omitting the has check:
const person = persons.get(id);
if(person) {
// do stuff
}
Alternatively persons.get(id, DEFAULT_PERSON) might always return a person object, but then you have to do if(person === DEFAULT_PERSON) which is even uglier than the exclamation mark
Or you disable strictNullChecks.
I've realized that we already solve this problem in the functional paradigm with the concept of Option. We can insert the potential value in an Option monad and work with the value if there is one, and safely fail when there is none.
I'll link my codesandbox, where in App.tsx I construct the problem and in App2.tsx I solve the problem. So if you're interested, have a look.

Is it possible to store in Redux a just new-made object posted to MongoDB and have access to its ObjectId without making a GET request

I have a store made with Redux who stores locally an array of object. Also, this array is stored in a mongo database.
Since my application may not have access to internet at every moment, when I add one object to the array, I POST it to mongo and since it is asynchronous it will just work when my app will catch the network.
At the same time, I update my reducer, I just add the same object, not the one that I would GET from the mongodb database after update.
But then, my local array have the new object without the ObjectID generated by mongo. So if I need to access it later via his _id, I can't.
I can't afford making a new ID field, I really need the mongo one.
const newObject = {
Name: 'name',
Visible: true,
};
let nextArray = [...oldArray, newObject];
this.props.dispatch({type:'ARRAY_UPDATE', value: nextArray});
axios.post('http://localhost:4000/Array',nextArray )
Then my Redux array is [...oldArray, {Name:'name', Visible:true}]
While my mongo array is [...oldArray, { _id:ObjectId('5ca52869c8f23918407535b2'), Name:'name', Visible:true}]
It's inconvenient since I need the _id, working with the local array.
Would it be safe to generate myself an _id ?
If yes, then I'm pretty sure this library (https://www.npmjs.com/package/bson-objectid) would do the work, otherwise, is there a safer way ?
Thanks.

Is there any way to update a specific index from the array in Firestore

Is there any way to update a specific index from the array in Firebase/firestore?
export const editComment = (comment) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
const firestore = getFirestore();
firestore.collection('topics').doc(comment.topicId).update({
comments: <--- this is array of objects
}).then(() => {
dispatch({ type: 'EDIT_COMMENT' })
}).catch((error) => {
dispatch({ type: 'EDIT_COMMENT_ERROR', error})
})
}
}
Is there any way to update a specific index from the array in Firestore?
No, there is not! This is not possible because if you want to perform an update, you need to know the index of that particular element. When talking about Cloud Firestore arrays, the things are different that you might think.
Because we are creating apps that can be used in a multi user environment, try to think what might happen if a user wants to edit a value at index 0, some other user wants to delete the value at index 0 and in the same time some other user might want to add another item at index 0. For sure, you'll end up having very different results and why not, get even array out of bounds exception. So Firestore actions with arrays are a little bit different. So you cannot perform actions like, insert, update or delete at a specific index.
If those two methods do not help you enough, you should get the entire document, get the array, modify it and add it back to the database.
Turn the array into it's own separate document and update the field in there. That's what I did. I had to restructure my database a bit in order to do so.
for me, I'm using firebase SDK for flutter, and nodeJS env. for cloud functions,, and I discovered the below solution.
this is a little bit of a hacky workaround
maybe we can save the list in a form of map not an array,, by using the array indexes as key strings to the sub maps
so you have structured the data like this in cloud fire store
key1: "value1" --> string
key2: --> map
> "0": {subKey1: "subValue1", subKey2: "subValue2"}
> "1": {subKey3: "subValue3", subKey4: "subValue4"}
> "2": {subKey5: "subValue5", subKey6: "subValue6"}
for example : if you want to update the subValue4, you may do this
await docReference.update({key2.1.subKey4: "theNewValueHere"});
and this ends up updating that document in cloud firestore to a document that looks like this
key1: "value1" --> string
key2: --> map
> "0": {subKey1: "subValue1", subKey2: "subValue2"}
> "1": {subKey3: "subValue3", subKey4: "theNewValueHere"}
> "2": {subKey5: "subValue5", subKey6: "subValue6"}
if you notice in firebase,, it updates the entire field key2 in this operation,, but gave you an easier access to update that index..
My problem is that I have to restructure all fields having list of maps to become maps within a map to have that access
And I will not do that,, will not refactor my entire db to do that,, I retrieve the entire doc,, (costs 1 read) modify at client and update the entire doc again (1 write)
I don't like it, but maybe someday I would use it

Smart way to push object to firebase

I have an object that I want to push to the firebase realtime database, looking like this:
userProfile = { name: "Jon", age: 25, gender: "male", ...plenty more attributes}
If I want it in firebase, I could write it like this:
return firebase.database().ref('/userProfile').push({
name: userProfile.name,
age: userProfile.age,
gender: userProfile.gender,
....
}).
But since I have plenty of objects with many attributes I would prefer not writing it by hand. Loops are not allowed in push (). I could push the whole object like this:
return firebase.database().ref('/userProfile').push({
userProfile: userProfile
}).
But it will create an additional child node like
ref/userProfile/123someId/userProfile/name
which is bad practise because it disallows using filters and more later on.
Is there a more effective way to push the attributes of an entire object without writing down every key/value pair?
The answer could not be easier, but in case someone else stumbles across the same issue:
firebase.database().ref('/userProfile').push(userProfile)
Thanks guys

local storage expiring data

I am using localStorage to save conversations client-side to save space server-side in my db. In order to do it I use an object like this:
users = {
478vh9k52k: {
name: 'john',
messages: []
},
42r66s58rs: {
name: 'jack',
messages: []
}
};
I then use users[id].messages.push(msgObj) to push new messages inside the right user ID. Lastly I use JSON.stringify and then save the resulting string.
Problem with this is that slowly the string will grow, thus filling in the limits. It is not too much of a problem the length of the messages array, because I truncate it, but the existence of old users not being necessary anymore.
Question is simple: how can I delete the old users that are contained in the 'users' object? I was thinking to add a timestamp as a key inside the object and then accessing random users to check on them at every save.
Or is there a better way to do this?
why access them randomly? you could slice up your storage in days instead, with a
localStorage["chatLogs"] = {
"13........0" : {
bob: {},
alice: {},
christoffelson: {}
}
"13....86400" : {
bob: {},
alice: {},
christoffelson: {}
}
}
and then run through your object by its keys. If they're older than a day, delete them. Alternatively, you can have a look at using indexdb instead of localStorage if you're going to do a lot of querying/filtering.

Categories