How to use store in Vue/ Nuxt plugin? - vue.js

I am writing a nuxt app that authenticates with a backend. I have a http plugin that intercepts all http requests. I need to add an auth token to all requests, the token is in the store. What I want to know is, how do I access the store from the plugin?
import axios from 'axios';
var api = axios.create({
baseURL: 'http://127.0.0.1:8000/api/'
});
api.interceptors.request.use(function (config) {
config.headers = {
'Authorization': 'Bearer' + **how do access store?**
}
return config;
}, function (error) {
return Promise.reject(error);
});
export default api;
Thanks

You can try to use app store from context in plugin.
Your plugin need some changes:
import axios from 'axios';
var api = axios.create({
baseURL: 'http://127.0.0.1:8000/api/'
});
export default (context, inject) => {
api.interceptors.request.use(function (config) {
config.headers = {
'Authorization': 'Bearer' + context.app.$store.state.your_path_to_token
}
return config;
}, function (error) {
return Promise.reject(error);
});
return api;
}
One more way it's create store/index.js file and import them into plugin.

Related

How to get browser cookie inside apollo client using nextjs for SSR, SSG or CSR?

I have graphql api using nestjs, on login i am getting jwt token and storing it in cookie using universal-cookie. For frontend i am using nextjs with apollo client, now i need to get that token from cookie and send it along apollo client as authorization header but inside apollo client cookie always return undefined.
apolloClient.ts
import { ApolloClient, createHttpLink, InMemoryCache } from "#apollo/client";
import { setContext } from "#apollo/client/link/context";
import { getCookie } from "../utils/cookies";
const httpLink = createHttpLink({
uri: "http://localhost:30001/graphql",
});
const authLink = setContext((_, { headers }) => {
const token = getCookie("medToken");
console.log(token); // getting undefined
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
},
};
});
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});
index.tsx
const { data }: { data: AuthUserRes } = await client.query({
query: gql`
query Query {
getAuthUser {
id
email
name
}
}
`,
});
return {
props: {},
};

Fetch data before rendering components in Vuejs

I am using Vuejs with Vuex and I have actions that are used to fetch data from the database, I want the fetch to be before rendering the components depended on this data. So where can I put these actions in my code ?
Mounted / BeforeMounted
Created
On Vuejs 3 you have onMounted
https://vuejs.org/api/
You can use your action (ex: getData) on onMounted hook
and you can use async await to be sure that your action call is done before moving to the next step
here is an exemple (i used axios just for the exemple you are free to use any methode to get your data) :
<template>
<h1>My component</h1>
</template>
<script>
import axios from 'axios'
export default {
name: 'MyComponent',
setup() {
const baseUrl = 'your-api-base-url'
const apiClient = axios.create({
baseURL: baseUrl,
withCredentials: false,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
const getData = async() => {
try {
return await apiClient.get('/api-path', {}) // here i call my
api to get data you can call your function
} catch (error) {
throw new Error(error)
}
}
onMounted(() => {
getData()
})
}
}
</script>

axios cancel is not working in react native redux

I am using axios for api call in react native application. I have redux for managing state in the application. I am trying to cancel the axios request when the component is unmounted but it is not cancelling.
import axiosMaker from '../../axios'
useEffect(() => {
const source = axios.CancelToken.source()
props.fetchFile(fileName, source.token)
return() => {
console.log('un mounting document view')
source.cancel()
}
},[])
//redux action
export const fetchFile = (location, token) => {
return async (dispatch) => {
dispatch(fetchFileRequest())
const config = {
path : location,
}
let axiosObj = await axiosMaker()
try{
axiosObj.post('download', config,
{
headers :{
'authorization' : `Bearer ${accessToken}`
}
},
{
cancelToken: token
}
)
.then(async response => {
console.log('doucment view success')
dispatch(fetchFileSuccess(response.data))
})
.catch(error => {
console.log('doucment view failure')
dispatch(fetchFileFailure(error))
})
} catch(error){
if(axiosObj.isCancel(error)){
console.log('request is canceled')
}
console.log('hello world')
}
}
}
What am I doing wrong here? How to cancel the axios call in redux?
I was sending accessToken and cancelToken separately. I sent it together.
axiosObj.post('download', config,
{
headers :{
'authorization' : `Bearer ${accessToken}`
},
cancelToken : token
}
)
and another changes is isCancel() function is available in the axios object itself not in the customize axios object. So, I imported the axios
import axios from 'axios'
and called isCancel function in this object, not in the axiosMaker object.
if(axios.isCancel(error)){
console.log('request is canceled')
}

Vue Axios local stored token is undefined

In Vue I am building a small Userprofile page. It is build on token-authentication using Axios. When mounting this page the token is undefined.
with login a token is placed in the localStorage.
The Axios Get request is build outside the Vue component
Api.js
import axios from 'axios'
export default () => {
return axios.create({
baseURL: `http://localhost:8081/`
})
}
Get request
import Api from '#/services/Api'
let config = {
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
}
}
export default {
index () {
return Api().get('user/profile', config)
}
}
Vue
<script>
export default {
data: () => ({
user: {}
}),
mounted () {
this.user = UserProfileService.index
console.log(UserProfileService.config)
}
}
</script>
There are many advices and I tried them all. With tics, with commas etc. Who sees the big picture?
Use a request interceptor to set the Authorization header:
// Api.js
export default () => {
const instance = axios.create({
baseURL: `http://localhost:8081/`
})
instance.interceptors.request.use(function (config) {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
return instance
}
I added the code from digital drifter, and solved the problem (with help) with changing the mounted function in Vue.
mounted () {
console.log('mounted')
UserProfileService.index()
.then((res) => {
this.user = res.data
})
}

Set axios authorization header depends on store changes

I am new to Vue (I am a react person) and I am having this problem.
axios.js
import store from '../../store/index';
import axios from 'axios'
const API_URL = process.env.API_URL;
const token = store.getters.auth.token;
export default axios.create({
baseURL: API_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
})
store/index.js
import auth from './modules/auth'
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
state: {},
getters : {},
mutations: {},
actions:{},
modules: {
auth
},
strict: debug,
})
modules/auth
import { AUTH_SUCCESS, AUTH_GUEST } from '../actions/auth'
import axios from '../../util/axios/axios'
import Vue from "vue";
const state = {
token: localStorage.token || '',
};
const getters = {
token: state => state.token
};
const actions = {
[AUTH_GUEST]: async ({commit}) => {
await axios.post('auth/register',)
.then(response => {
commit(AUTH_SUCCESS, response);
})
.catch(error => {
console.log(error);
});
},
};
const mutations = {
[AUTH_SUCCESS]: (state, resp) => {
state.token = resp.data.token;
},
}
export default {
state,
getters,
actions,
mutations,
}
when trying to get the store from store/index it returns undefined.
probably the axios has been called before the store has been initialized.
but how can I deal with it?
the flow of the app is.
user register->get token->update store with this token->add to the axios header.
so for now on, all calls to the api will have the token provided.
First of all, you should be careful with Vue's reactivity caveats which affect Vuex aswell. In your case, you're adding a new property inside an object in a mutation.
Back to the main issue, your axios.js file is being executed before the Store instance is built, that's why you cannot access to it and you get undefined.
What I'd do is:
axios.js
import axios from 'axios';
const API_URL = process.env.API_URL;
export default (store) => axios.create({
baseURL: API_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${store.getters.auth.token}`
}
});
and then in your main file, where you have the main Vue instantiation I'd just run the function there, exporting the return of that function.