Here's what I want to do:
I am looking to store user preferences (Possibly 2-3 users max) in a cookie so they are readily available.
Upon login, I check if I have an existing 'users' cookie and if not, I create it. If it exists, I check if my current user is inside this cookie. If not, I add him, with empty prefs.
vue: 2.4.16
vue-cookies: 1.7.4
loggedIn (userId) {
this.profile = userId
this.userConnected = true
if (this.$cookies.isKey('users')) {
const userBase = JSON.parse(this.$cookies.get('users'))
const found = userBase.findIndex(user => user.profile === this.profile)
if (found === -1) {
console.log('new user, add to cookie')
const newUser = {
profile: this.profile,
preferences: {
cursor: null,
wallpaper: null,
theme: null
}
}
userBase.push(newUser)
this.$cookies.set('users', JSON.stringify(userBase), 604800)
}
} else {
console.log('no cookie, create users cookie')
const newUsers = [
{
profile: this.profile,
preferences: {
cursor: null,
wallpaper: null,
theme: null
}
}
]
this.$cookies.set('users', JSON.stringify(newUsers), 604800)
}
So far so good. Everything seems to work properly.
I then have my function to update preferences and update the cookie. The problem occurs when I have more than one users in my cookie. The first object in my cookie array will always get modified properly, but any other user in the Array will be ignored completely. This only happens with the cookie, the data that I'm pushing into the cookie is looking good. Here's more details:
updatePreferences (preference, data) {
//- We are getting the Users cookie, and finding the current active user
const globalPreferences = JSON.parse(this.$cookies.get('users'))
const userIndex = globalPreferences.findIndex(user => user.profile === this.$store.state.User.userProfile)
const currentUser = globalPreferences[userIndex]
if (preference === 'wallpaper') {
currentUser.preferences.wallpaper = data
globalPreferences.splice(userIndex, 1, currentUser)
//- globalPreferences is always properly updated. The console log always reflects the changes
const updatedData = JSON.stringify(globalPreferences)
//- The cookie does not properly update. Only the first index ever gets updated, the rest never changes.
this.$cookies.set('users', updatedData, 604800)
}
}
I am definitely lost here. I have tried removing the cookie before updating it again, but without luck either. Any help would be appreciated. Thanks!
First user update - Console log (Works properly)
Second user update - Console log (Cookie does not update value)
The data I was trying to push into the cookie was too big. I'm gonna use localStorage for now as it properly updates my data, and will make sure to clean the unused informations.
Related
Here is a reproducable stackblitz -
https://stackblitz.com/edit/nuxt-starter-jlzzah?file=components/users.vue
What's wrong? -
My code fetches 15 items, and with the bottom scroll event it should fetch another 15 different items but it just fetches same items again.
I've followed this bottom video for this implementation, it's okay in the video but not okay in my stackblitz code:
https://www.youtube.com/watch?v=WRnoQdIU-uE&t=3s&ab_channel=JohnKomarnicki
The only difference with this video is that he's using axios while i use useFetch of nuxt 3.
It's not really a cache issue. useFetch is "freezing" the API URL, the changes you make to the string directly will not be reliably reflected. If you want to add parameters to your API URL, use the query option of useFetch. This option is reactive, so you can use refs and the query will update with the refs. Alternatively, you can use the provided refresh() method
const limit = ref(10)
const skip = ref(20)
const { data: users, refresh: refreshUsers } = await useFetch(
'https://dummyjson.com/users',
{
query:{
limit,
skip
}
}
);
//use the data object directly to access the result
console.log(users.value)
//if you want to update users with different params later, simply change the ref and the query will update
limit.value = 23
//use refresh to manually refresh the query
refreshUsers()
This results in a first API call http://127.0.0.1:8000/api/tasks?limit=10&skip=20 and then a second with the updated values http://127.0.0.1:8000/api/tasks?limit=23&skip=20
You can leave the cache alone, as it is just a workaround, and will not work reliably.
[Updated] The useFetch() documentation is now updated as described below.
The query option is not well documented yet, as discussed in this nuxt issue. I've created a pull request on nuxt/framework to have it reflected in the documentation. Please see a full explanation below:
Using the query option, you can add search parameters to your query. This option is extended from unjs/ohmyfetch and is using ufo to create the URL. Objects are automatically stringified.
const param1 = ref('value1')
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
query: { param1, param2: 'value2' }
})
This results in https://api.nuxtjs.dev/mountains?param1=value1¶m2=value2
Nuxt3's useFetch uses caching by default. Use initialCache: false option to disable it:
const getUsers = async (limit, skip) => {
const { data: users } = await useFetch(
`https://dummyjson.com/users?limit=${limit}&skip=${skip}`,
{
initialCache: false,
}
);
//returning fetched value
return users.value.users;
};
But you probably should use plain $fetch instead of useFetch in this scenario to avoid caching:
const getUsers = async (limit, skip) => {
const { users } = await $fetch(
`https://dummyjson.com/users?limit=${limit}&skip=${skip}`
);
//returning fetched value
return users;
};
I have a page to update user data, everything is running correctly and the data has changed with the latest in the database. But the value in the next auth session does not change, how to synchronize the newly updated user data with the user data in the next auth session
First you have to update the data on [...nextauth].js
It keeps track of user with the server session, but you want fresh data from your server. Here is how I did it :
callbacks.session = async function session({ session, token }) {
// we can fetch info from back end here to add it to the sessio
session.user = token.user;
session.jti = token.jti;
// If user is logged, we refresh his session
if (token?.user?.id) {
const url =
routes.api.entities.shop.get.byId.build(token?.user?.id);
let apiResp = await axios.get(url, {});
session.user = { ...apiResp.data };
token.user = { ...apiResp.data };
}
return session;
};
So here, the session that should have been the old one of the server is replaced by the one of my DB.
Then, you have to update it client side.
The data on client side does update if you click on another tab and click again on your tab.
It seems useless, but what about automating it ?
Just use this :
const reloadSession = () => {
const event = new Event("visibilitychange");
document.dispatchEvent(event);
};
And calling it directly on your react page will update everything.
reloadSession();
Im having issues with delete request, my post, get are working fine.
What am I doing wrong?
removeUser(id) {
axios.delete('https://jsonplaceholder.typicode.com/users' + id)
.then(function(response) {
const user = response.data;
this.users.splice(id, user);
});
if response.status === 204, then delete is succeed.
for the client, here is an axios example, notice there is a ' after users
destroy() {
return request.delete('/api/users/' + id)
}
for the server, here is an Laravel example:
if( $article->delete() ) {
return response()->json(null, 204);
} else {
abort(409);
}
I can see only 1 problem on the code you provided.
You're trying to modify the Vue instance $data users object by executing this.users.splice(id, user);. But you're inside the callback function and this no longer represents the Vue instance.
To fix this & make the users object actually modify after the response comes you'll need to do it like this :
removeUser(id) {
let that = this;
axios.delete('https://jsonplaceholder.typicode.com/users' + id)
.then(function(response) {
const user = response.data;
that.users.splice(id, user);
});
Now , I don't have any code from the back-end so I'll just make some assumptions :
The route might not be well defined > if you're using NodeJS then you should check your routes , it should look like this :
router.route('/users:id').delete(async function(req,res,next){ /* ... */ });
You might have a route problem because / is missing before the user value
1 hint : Again , if you're using NodeJS , you could use this inside your .delete route :
res.status(200).json({ errorCode : null , errorMessage : null , users : [] });
To see if you're receiving it on front-end.
I think you do need to append the trailing '/' to the URL, that way the URL is properly formed, such as "https://jsonplaceholder.typicode.com/users/123" (rather than "users123" at the end).
Aside from that, the first parameter to Array.prototype.splice is the position where item removal should begin. The second (optional) parameter, deleteCount, is the number of items to remove. Beyond deleteCount, you can pass a collection of objects which are to be inserted after the start position and after items have been removed.
You just need to find the object in your this.users array and remove it. If you want to use Array.prototype.splice for that, then you can use Array.prototype.findIndex to find the index of the user in the array then remove it:
// Find the index of the item to remove
const indexOfUserToRemove = this.users.findIndex(u => u.id === id);
// Call splice to remove the item
this.users.splice(indexOfUserToRemove, 1);
I'm wondering what's the best solution to reset all my store once a user logout.
Typically I have an app where I log in and sometimes in dev mode I need to switch from account (which can be the case in live mode). And obviously I've some issues when I log with another user, some store infos are still there and belongs to other user (dunno if I'm clear).
I already clear some module from my store inside my logout function inside auth.js. But as my app is growing, and store (decoupling in several modules) also, I just wonder what's the best approach to reset all my store at once, with initial value/state.
Any thoughts ?
This is how I'm clearing out some data from the store in Nuxt.
clearToken(state) {
state.token = null
state.refresh = null
state.currentUserData = null
},
logout(vuexContext, req) {
vuexContext.commit('clearToken')
Cookie.remove('jwt')
Cookie.remove('jwt_refresh')
Cookie.remove("tokenExpiration");
Cookie.remove("userData");
if (process.client) {
localStorage.removeItem('refresh');
localStorage.removeItem('token');
localStorage.removeItem("tokenExpiration");
localStorage.removeItem("userData");
if (!localStorage.getItem('token')) {
$nuxt.$router.push('/login/');
}
}
}
You can clean all vuex data using: localStorage.vuex = ''
I'm currently working on Ionic 2 app with Parse Server backend.
I implemented signed up process. No problems here, everything works as expected: new account is created, user is logged in after sign up and current user exists.
Now I want to use current user and bypass sign up/login page next time user opens the app (if the user is already logged in ). The Parse documentation clearly states:
“It would be bothersome if the user had to log in every time they
open your app. You can avoid this by using the cached
current Parse.User object. Whenever you use any signup or login
methods, the user is cached in localStorage.”
In my case, however, I can't manage to make it work. I create current user according to Parse documentation during initialization process of the app:
var currentUser = Parse.User.current();
if (currentUser) {
// do stuff with the user
} else {
// show the signup or login page
}
Every time I open the app after successful sign up the current user is NULL.
Any ideas?
I kinda understand what's going on, but still don't understand why.
During signup or login Parse is supposed to save current user to local storage, but if local storage is not available for some reason, it saves it to memory map. And this is what happens in my case: Parse always saves current user to memory map, which is, of cause, temporary storage. Hence, every time I reload the app, Parse memory map is empty. I don't understand why in my environment Parse decides that local storage is unavailable. I couldn't find in the code where this decision is made. It seems to me that memory map is default (which is probably not true). Could it be that local storage functionality is not implemented yet in the open source version of Parse? Or does it have something to do with Ionic2 implementation?
Is there anybody out there from Parse team who is familiar with this part of Parse code?
Thanks.
Hi I use Local Storage.
import { Component } from '#angular/core';
import { NavController,Alert,Storage,LocalStorage } from 'ionic-angular';
import {HomePage} from'../home/home';
import {UserdetailPage} from'../userdetail/userdetail';
declare var require:any;
var Parse = require('parse/node');
#Component({
templateUrl: 'build/pages/user/user.html',
})
export class UserPage {
public currentUser:any;
public local:any;
username:string="";
password:string="";
repassword: string="";
sign:string = "SIGN IN";
constructor(private nav: NavController) {
Parse.initialize(XXXXX);
Parse.serverURL = 'XXXXXX';
this.local = new Storage(LocalStorage);
this.currentUser = this.local.get('userid');
console.log(this.currentUser);
}
signin(){
console.log("username:"+this.username);
console.log("password:"+this.password);
if(this.username!="" &&this.password!=""){
if(this.repassword!=""){
// Register User Session
this.register();
}
else if(this.repassword==""&&this.username!=""&&this.password!=""){
this.login();
}
}
}
changeSign(s:string){
console.log(s);
if(s!="")
this.sign = "SIGN UP (Register New Account)";
else
this.sign ="SIGN IN";
}
register(){
if(this.repassword==this.password){
var parseuser = new Parse.User();
parseuser.set("username",this.username);
parseuser.set("password",this.password);
parseuser.signUp(null, {
success:user=>this.registerSucessAlert(),
error: error=>this.registerFailAlert("Register Fail, The user name exists or Server is down")
});
}
else{
this.registerFailAlert("Password is not the same");
}
}
login(){
console.log("Login");
Parse.User.logIn(this.username, this.password, {
success:user=>this.loginSucessAlert(),
error:error=>this.loginFailAlert()
});
}
loginSucessAlert(){
this.currentUser = Parse.User.current().id;
this.local.set('userid',this.currentUser);
let alert = Alert.create({
title:'Login',
subTitle:'Hi '+this.username+', Press to Continue.',
buttons:[{text:'OaaaK',
handle:()=>{this.nav.setRoot(UserdetailPage);}}]
});
this.nav.present(alert);
}
loginFailAlert(){
let alert = Alert.create({
title:'Login',
subTitle:'Login Error',
buttons:['OK']
});
this.nav.present(alert);
}
registerSucessAlert(){
this.currentUser = Parse.User.current().id;
this.local.set('userid',this.currentUser);
let alert = Alert.create({
title:'Resgiter',
subTitle:'Thank you'+this.username+' for register, Press to Continue.',
buttons:['OK']
});
this.nav.present(alert);
}
registerFailAlert(err:string){
let alert = Alert.create({
title:'Register Fail',
subTitle:err,
buttons:['OK']
});
this.nav.present(alert);
}
}