Unable to save login session in Vue - vue.js

I have a login page that I can login via google, and when I login I get the parameters of the user. The problem is when I refresh the page the parameters are not saved.
This is my code:
export default {
name: "App",
data() {
return {
isLogin: false,
};
},
methods: {
async logOut() {
const result = await this.$gAuth.signOut();
this.isLogin = false;
console.log(`result`, result);
},
async login() {
const googleUser = await this.$gAuth.signIn();
console.log("googleUser", googleUser);
console.log("getId", googleUser.getId());
console.log("getBaseProfile", googleUser.getBasicProfile());
console.log("getAuthResponse", googleUser.getAuthResponse());
console.log(
"getAuthResponse$G",
this.$gAuth.GoogleAuth.currentUser.get().getAuthResponse()
);
this.isLogin = this.$gAuth.isAuthorized;
},
},
};
</script>
As a solution I want to save the session inside a cookie, so I tried to add a dummy cookie to my code, as follow:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-cookies#1.7.4/vue-cookies.js"></script>
<template>
<div id="app">
<button #click="login()">Login</button>
Is login: ? {{ isLogin }}
<button #click="logOut()">LogOut</button>
</div>
</template>
<script>
// Require dependencies
var Vue = require('vue');
var VueCookie = require('vue-cookie');
// Tell Vue to use the plugin
Vue.use(VueCookie);
// From some method in one of your Vue components
this.$cookie.set('test', 'Hello world!', 1);
// This will set a cookie with the name 'test' and the value 'Hello world!' that expires in one day
// To get the value of a cookie use
this.$cookie.get('test');
// To delete a cookie use
this.$cookie.delete('test');
export default {
name: "App",
data() {
return {
isLogin: false,
};
},
methods: {
async logOut() {
const result = await this.$gAuth.signOut();
this.isLogin = false;
console.log(`result`, result);
},
async login() {
const googleUser = await this.$gAuth.signIn();
console.log("googleUser", googleUser);
console.log("getId", googleUser.getId());
console.log("getBaseProfile", googleUser.getBasicProfile());
console.log("getAuthResponse", googleUser.getAuthResponse());
console.log(
"getAuthResponse$G",
this.$gAuth.GoogleAuth.currentUser.get().getAuthResponse()
);
this.isLogin = this.$gAuth.isAuthorized;
},
},
};
</script>
But I got Uncaught TypeError: Vue.use is not a function.
What am I doing wrong?
Is there a better way to save the login session?

I think you skipped this line:
https://github.com/alfhen/vue-cookie#installation
Or do it the cool way and load it in your main.js/app.js
You should register that VueCookie plugin in the file where you start the Vue instance.
See: https://v2.vuejs.org/v2/guide/plugins.html

Related

Vue useStorage (usevue) always starting clean rather than importing state in Pinia store

I built my app on top of vitesse-nuxt3, and all is going well except for trying to use LocalStorage via vueuse.
Component:
<script setup lang="ts">
const { test } = useTestStore()
</script>
<template>
<div>
<pre>{{ test }}</pre>
<hr>
<input
:id="slug"
v-model="value"
type="text"
>
</div>
</template>
Pinia Store:
import { acceptHMRUpdate, defineStore } from 'pinia'
import { useStorage } from '#vueuse/core'
export const useTestStore = defineStore('test', () => {
const test = ref(
useStorage('test', {
initials: 'It is initials',
}),
)
return ({
test,
})
})
if (import.meta.hot)
import.meta.hot.accept(acceptHMRUpdate(useTestStore, import.meta.hot))
I watch it set the data (in Chrome's dev tools), but it always reloads the default data instead rather than persisting between refreshes.
Thank you.
The problem in your demo is that the component is being rendered server-side, which has no Local Storage, so useStorage() defaults to the given initial value.
One workaround is to render the component on the client only, using the <client-only> component:
<client-only>
<component-that-uses-local-storage />
</client-only>
demo
for store like this like #tony19 said
export const useAuthStore = defineStore({
id: 'auth.store',
state: () => {
token: {
accessToken: useStorage('accessToken', [XXXX], undefined, { serializer: StorageSerializers.object }),
refreshToken: useStorage('refreshToken', [YYYY], undefined, { serializer: StorageSerializers.object })
},
},
})
[XXXX] [YYYY] is default value
after ssr pinia.state.value become to
window.__INITIAL_SSR_CONTEXT__ = {
state: {
"auth.store": {
"token":{
"accessToken":[XXXX],
"refreshToken":[YYYY]
}
}
}
}
on client side reasign the json object to store like this
const ssr_state = (window as any)['__INITIAL_SSR_CONTEXT__']?.['state']
if (ssr_state) {
pinia.state.value = ssr_state
}
so the accessToken, refreshToken property changes to plan object on client side, you can change it but the storage don't update.
my solution:
add one action to store
actions:{
// ...
// call this once when isSSR is true on client side entry
reasignToken() {
this.token = {
accessToken: useStorage('accessToken', this.token.accessToken, undefined, {
serializer: StorageSerializers.object
}),
refreshToken: useStorage('refreshToken', this.token.refreshToken, undefined, {
serializer: StorageSerializers.object
})
}
},
// regular call on server side and client side
setToken(token) {
//...
}
}

how to migrate from Nuxt 2 Axios to usefetch in Nuxt3

I am trying to migrate a small project from Nuxt2 to Nuxt3. in Nuxt2, I used axios for making API calls.
now i want to fetch in nuxt3 but Axios doesn't work here.
how to migrate this code to usefetch method in Nuxt3.
this is what i had in nuxt2
<script>
import axios from "axios";
export default {
data() {
return {
allDestinations: [],
allSubDestinations: [],
allTours: [],
form: "",
};
},
async asyncData({ route }) {
let { data: countrydata } = await axios.get(
`${process.env.backendapi}/dests/getcountry/${route.query.countryid}`
);
let { data: allDest } = await axios.get(
`${process.env.backendapi}/dests/getmaindests?limit=5000`
);
let { data: allSubDest } = await axios.get(
`${process.env.backendapi}/dests/getsubdests?limit=5000`
);
let { data: alltours } = await axios.get(
`${process.env.backendapi}/tours/gettours?limit=10000`
);
return {
form: countrydata,
allDestinations: allDest.results,
allSubDestinations: allSubDest.results,
allTours: alltours.results,
};
},
};
</script>
The equivalent to that in Nuxt3would be the following.
.env
NUXT_PUBLIC_TEST_URL="https://jsonplaceholder.typicode.com"
nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
runtimeConfig: {
public: {
testUrl: '', // fallback empty string, must be present tho
},
},
})
With this in any page
<template>
<section>
<div>{{ todo.title }}</div>
<div>{{ user.email }}</div>
<div>{{ photos }}</div>
</section>
</template>
<script setup>
const { testUrl } = useRuntimeConfig()
const route = useRoute() // let's suppose that `countryid` equals 1
const { data: todo } = await useFetch(`${testUrl}/todos/1`)
const { data: user } = await useFetch(`${testUrl}/users/${route.query.countryid}`)
const { data: photos } = await useFetch(`${testUrl}/photos/`)
</script>
More details regarding data fetching can be found here: https://v3.nuxtjs.org/guide/features/data-fetching
But overall, useFetch is blocking and doing what you expect.
If you cannot use script setup, you need to write it like this: https://v3.nuxtjs.org/guide/features/data-fetching#using-async-setup
Here is the documentation regarding env variables: https://v3.nuxtjs.org/guide/features/runtime-config#environment-variables

nuxt.js call stack size render issue when login with IBM App Id

I have a problem using IBM App Id and Nuxt.js project. When I am trying to do the signIn method from
IBM AppId, it thows an error, error setAlgAndProvider hash alg set fail alg=sha256/RangeError: Maximum call stack size exceeded
that's my code from my login component:
<template>
<div class="login" #click="login">
CLICK TO LOGIN
</div>
</template>
<script>
export default {
name: "Login",
data: () => ({
appID: null
}),
mounted() {
this.appID = new AppID();
this.init();
},
methods: {
async init() {
await this.appID.init({
clientId: '************',
discoveryEndpoint: '********'
});
},
async login() {
const tokens = await this.appID.signin();
console.log("***TOKENS***", tokens);
}
}
}
</script>
Any ideas? I see that error on my browser (attached image)

Why is Vuex not detected after refresh page? (nuxt)

Vuex is not detected after refresh, but all data is output to the console. Also after refresh, some components behave incorrectly. For example, I use vee-validate and all the rules and fields I get from the back, after refresh the validation rules disappear, but the fields are displayed
Vuex works on all pages but after refresh only on the home page
stroe/index.js
export const state = () => ({});
const map = {
ru: "ru",
uk: "uk-ua"
};
export const getters = {
lang(state) {
return map[state.i18n.locale];
}
};
export const mutations = {};
export const actions = {
async nuxtServerInit({ state, dispatch }) {
try {
await dispatch('category/getCategories', {
});
} catch (err) {
console.log('nuxt server init error', err);
}
}
};
home page (everything works)
<template>
<div>
<main class="home-page">
<banner />
<section class="home_page">
<div class="container">
<phone-pay />
<card-pay />
<categories :categories="categories" :services="services" />
<main-banner />
</div>
</section>
</main>
</div>
</template>
<script>
import Banner from "#/components/Index/Banner";
import PhonePay from "#/components/Index/PhonePay";
import CardPay from "#/components/Index/CardPay";
import Categories from "#/components/Index/Categories";
import MainBanner from "#/components/Index/MainBanner";
export default {
components: {
Banner,
PhonePay,
CardPay,
Categories,
MainBanner
},
async asyncData({ store, app: { $api }, error, req }) {
try {
const {
data: { data: categories, included: services }
} = await $api.CategoryProvider.getPopularCategories({
params: {
include: "services"
}
});
return {
lang: store.getters.lang,
categories,
services
};
} catch (e) {
console.log("error index", e);
error({ statusCode: 404, message: "Page not found" });
}
}
};
</script>
category (does not work)
<template>
<services-viewer :initial-services="initialServices" :category="category" :init-meta="initMeta" />
</template>
<script>
import ServicesViewer from "#/components/UI/ServicesViewer";
export default {
components: {
ServicesViewer
},
async asyncData({ store, route, error, app: { $api } }) {
try {
const {
data: { data: initialServices, meta: initMeta }
} = await $api.ServiceProvider.getServices({
params: {
"filter[category_slug]": route.params.id,
include: "category"
// "page[size]": serviceConfig.SERVICE_PAGINATION_PAGE_SIZE
}
});
await store.dispatch("category/getCategories", {
params: {}
});
const category = store.state.category.categories.find(
({ attributes: { slug } }) => slug === route.params.id
);
return {
initialServices,
category,
initMeta
};
} catch (e) {
const statusCode = e && e.statusCode ? e.statusCode : 404;
error({ statusCode });
}
}
};
</script>
install the below package:
npm install --save vuex-persistedstate
then change your store like below, then your data will be available after refresh the page.
// store/index.js
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate'
const createStore = () =>
new Vuex.Store({
plugins: [createPersistedState()],
state: {
},
mutations: {
},
getters:{
}
});
export default createStore;
for more details you can read from here.
I solved it. It was my mistake. I have a parallax plugin that works on the home page, but if you go to another page and refresh, the plugin starts and cannot find the item and breaks the page.
follow this link for your question
The nuxtServerInit Action
If the action nuxtServerInit is defined in the store and the mode is universal, Nuxt.js will call it with the context (only from the server-side). It's useful when we have some data on the server we want to give directly to the client-side.
For example, let's say we have sessions on the server-side and we can access the connected user through req.session.user. To give the authenticated user to our store, we update our store/index.js to the following:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}

Nuxt head() does not wait asyncData response for head

I have a nuxt code like this
<template>
<section>
<div>Hello Nuxt</div>
</section>
</template>
<script>
const fetchTheme = () => {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve({
title: "Fetched Title"
});
}, 100);
});
};
export default {
async asyncData() {
const theme = await fetchTheme();
return theme;
},
head() {
if (this.theme) {
return {
title: this.theme.title
};
} else {
return {
title: "Default title"
};
}
}
};
</script>
<style scoped>
</style>
While I do view source, it gives 'Default title' but I need the title fetched from API
Here is Code Code Sandbox
From the docs on asyncData:
Nuxt.js will automatically merge the returned object with the component data.
That means that what you're doing:
async asyncData() {
const theme = await fetchTheme();
return theme;
}
is analogous to this:
async asyncData() {
const theme = await fetchTheme();
return {
title: theme.title
};
}
Which means that the title is accessible by doing this.title instead of this.theme.title.
To fix this, simply modify the return format of asyncData, to return an object that has a theme property:
async asyncData() {
const theme = await fetchTheme();
return {
theme
};
}
This will properly add the theme property to the data property of the component.