In Vue2, how to remove observor functionality from object to save in cookie - vue.js

I have the following code fragment and would like to strip the observer functionality from the user.accounts object. How would I do that? this.$cookies is a reference to my vue-cookies instance
setUserAccount(user, account){
// var accounts = Object.assign({},user.accounts)
this.$cookies.set('AUTH_TOKEN', user.authHash);
this.$cookies.set('CURRENT_ACCOUNT', user.id);
this.$cookies.set('ACCOUNTS', user.accounts);
console.log(user.accounts);
},

Convert the object to a JSON string. That will remove all the Vue observer mechanisms.
const strAccounts = JSON.stringify(user.accounts)
this.$cookies.set('ACCOUNTS', strAccounts);
And to convert it back (without the observer functionality).
JSON.parse(strAccounts);
The only caveat is you need to watch out for circular references in your object, and functions will not get serialized.

Related

vuex-persistedstate not saving class methods

I'd like to preference this by saying my backgrounds in in C# so I like declaring methods within my classes. I've created a user class that contains properties and methods and I've added this to my vuex-persistedstate. One of the methods is a logout() method which clears out the properties. When I tried to invoke this method I got the following error:
TypeError: this.$data.user.logout is not a function
I then reviewed local storage and noted the user did not have reference to the class method. So I went ahead and copied the logic from the method into my vue component and it worked so I'm assuming the issue is vuex-persistedstate does not save references to methods which is why the method call did not work.
I'd like to declare the logout method in one location rather than spreading it out across vue components, what is the best practice for accomplishing this? Is it possible to do this in the class declaration or do I need a user helper file?
Sure Berco! My code is also up on GitHub so you can review it there too, but basically it seems to me that vuex does not store methods. The first file you should review is my user.js file:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/models/user.js
In this file I have a method called shallow clone which takes the info received from the API and assigns it to the user:
shallowClone(data) {
if (data !== undefined) {
this.id = data.id;
this.userName = data.userName;
this.firstName = data.firstName;
this.lastName = data.lastName;
this.nickName = data.nickName;
this.fullName = data.fullName;
this.email = data.email;
this.isActive = data.isActive;
this.isAdmin = data.isAdmin
this.isSuperUser = data.isSuperUser;
this.dateCreated = data.dateCreated;
this.dateUpdated = data.dateUpdated;
this.isLoggedIn = data.isLoggedIn;
}
}
You of course don't need to abstract this away but I've found it makes the code easier to maintain.
Then in the mounted() lifecycle hook I assign the user received from the API to the component user via the shallowClone method. Please bear in mind I've done additional work on this project and the login form is now it's own component which receives the user as a prop from the app:
https://github.com/Joseph-Anthony-King/SudokuCollective/blob/master/SudokuCollective.WebApi/client/src/components/LoginForm.vue
mounted() {
let self = this;
window.addEventListener("keyup", function (event) {
if (event.keyCode === 13) {
self.authenticate();
}
});
this.$data.user = new User();
this.$data.user.shallowClone(this.$props.userForAuthentication);
},
The full code can be reviewed here:
https://github.com/Joseph-Anthony-King/SudokuCollective
I found a solution... I'm working on improving it. Basically I use the values pulled from localstorage into vuex to create a new user object in the vue component that has reference to the methods located in my user class declaration. I recalled recommendations that we should create clones of objects pulled from vuex for use within the vue component. I'm still refining the code but that's basic idea.

Update entire object in an array of objects in Vuex store with Vue.set()?

I have a form that needs to reactively update an entire object in an array of objects in a state mutation. I know Vue.set() works well for updating a single property, but I'm curious if it works to just update the full object. Something like this:
Vue.set(state.objects, obj.id, newObject)
The use case would be for a form update where the properties that are modified would be inconsistent. I may also just be misunderstanding Vue.set() altogether. The docs are extremely brief on this, saying only:
When adding new properties to an Object, you should either:
Use Vue.set(obj, 'newProp', 123), or
Replace that Object with a fresh one. For example, using the object spread syntax we can write it like this:
state.obj = { ...state.obj, newProp: 123 }
Any advice on the best way to go about this would be greatly appreciated!
I was previously updating the object by finding the index and replacing it, but that seemed to lack reactivity. Example:
let index = state.objects.findIndex(o => o.id === obj.id)
if (index !== -1) {
state.objects[index] = new Object(obj)
return
}
state.objects.push(new Object(obj))

Mongoose: Why to convert a received data toObject

I was learning mongoose, and I am trying to figure out.
Why toObject() was needed to convert the data received into Object, when it was already in object form it seems
Here is the code:
UserSchema.methods.toJSON = function() {
var user = this;
var userObject = user.toObject();
return _.pick(userObject, ['_id', 'email']);
};
I cannot understand why toObject() was used to extract the meaningful properties from the object.
Thanks
toObject is a mongoose document method Document.prototype.toObject() which:
Converts this document into a plain javascript object, ready for storage in MongoDB.
You can more about it here
The reason it is called there is because a plain JS object is required in order to do the lodash _.pick which would create a new object with only _id and email properties.

set array of data into mobx array show proxy objects

I'm using react js with mobx and I get data from api.
the data I get is array of objects.
when I set the data into mobx variable then I see array of proxy objects(not sure what the proxy says). I'm trying just to set the array of objects I get from api into mobx variable.
my store
class UserStore {
#persist #observable token = null
#observable tasks = []
#observable done = false
#persist #observable email = ''
constructor() {
}
#action
getTasks = async () => {
try {
let response = await Api.getTasks()
console.log('getTasks',response.tasks)
this.tasks = response.tasks
console.log('my new tasks',this.tasks)
} catch (e) {
console.log(e)
}
}
as you can see here in the first block('black') the data i get from api, then i set the respnse.tasks into this.tasks.
this.tasks = response.tasks
console.log('my new tasks',this.tasks)
You can convert proxy to JS:
import { toJS } from 'mobx'
// example
toJS(response)
It depends on how you want to observe the data.
"I'm trying just to set the array of objects I get from api into mobx variable"
is not really your end-goal.
If you want your observers to:
option a: react when the array reference change
= No care for values in the array.
Use #observable.ref tasks.
option b: react when the references of each value in the array change
= No care for the individual objects properties.
Use #observable.shallow tasks.
option c: react on the individual objects properties too
= Make everything observable, references and object properties
Use #observable tasks like you do.
Like indicated in the comments, mobx5 is using Proxy and some behaviour might differ compared to previous version.
More info: Mobx arrays, Mobx decorators, shallow observability
Note: you would need to give more details if this does not help you, like your react component code.
In my case, toJS was not working because I had a class with a variable with the type of another class. So, I needed to create new objects from the JSON:
parsedArray.map(
(a) =>
new MyObj1({
id: a.id,
myObj2: new MyObj2({
label: a.label,
}),
title: a.title,
})
);
If you run debugger, stop the debugger. It messes the mobx's flow.

Why is js object losing properties in expressJS route

I'm trying to use a "configured object" as a controller in ExpressJS so I can reuse a bunch of code.
Taken from the express configuration:
var ctrl = new CRUDServiceAdapter(serviceConfig);
// list
// this works: ctrl.load()
app.get(serviceURL, ctrl.load);
And separately this is part of the object definition:
function CRUDServiceAdapter(serviceConfig){
this.config = serviceConfig;
this.logger = logModule.logger("service.controller." + serviceConfig.modelName);
};
CRUDServiceAdapter.prototype.load = function(req, res, next){
this.logger.debug("Creating an object model for " + this.config.modelName);
res.json({"msg": "Hello World"});
};
What I observe is the object property this.config is undefined when the method is called through an expressJS request. But if I call it directly on the object like in the comments ctrl.load() - the config object is populated as expected.
Why is the object losing it's property values when it's executing as a route?
Is there a way to fix it?
The context is lost:
You are not passing the object ctrl as parameter, only a method, so that method is called as any regular function, so this is not pointing at ctrl (I guess it is undefined), so try to change your code for:
app.get(serviceURL, ctrl.load.bind(ctrl));