how to transfer an object to a header fetchBaseQuery - api

I'm working with api for movies, and to create a request to the server, I need to pass it to the header object
{
'X-API-KEY': 'there is apikey',
'Content-Type': 'application/json',
}
I make requests using RTK Query
export const filmsApi = createApi({
reducerPath: 'awaitsFilms',
baseQuery: fetchBaseQuery({
baseUrl: url,
}),
endpoints: (build) => ({
getAwaitsFilms: build.query({
query: () => `top?type=TOP_AWAIT_FILMS`,
}),
}),
})
how do I pass this header object to fetchBaseQuery?

Documentation
import type { RootState } from './store'
const baseQuery = fetchBaseQuery({
baseUrl: '/',
prepareHeaders: (headers, { getState }) => {
const token = (getState() as RootState).auth.token
// If we have a token set in state, let's assume that we should be passing it.
if (token) {
headers.set('authorization', `Bearer ${token}`)
}
return headers
},
})

Related

Get token from endpoint

guys, I'm new in RN. I have a default login endpoint smth like this
export const authApi = api.injectEndpoints({
endpoints: build => ({
login: build.mutation({
query: credentials => ({
url: apiEndpoint.login,
method: 'POST',
body: credentials,
}),
}),
}),
});
export const {useLoginMutation} = authApi;
and i want to get auth token from store after login to prepare headers, but i don't know how to
export const api = createApi({
baseQuery: fetchBaseQuery({
baseUrl: apiConfig.apiBaseUrl,
prepareHeaders: (headers, {getState}) => {
const token = getState().api;
if (token) {
headers.set('Authorization', token);
}
headers.set('Accept', 'application/json');
return headers;
},
}),
endpoints: () => ({}),
reducerPath: 'api',
});
What is the correct way to make this? And another question if I want to make it persistent what can I use? I read about AsyncStorage but it's not a secure way

Rtk query always returns cached data. InvalidatesTags not doing anything

Can somebody tell me why I still get the cached data after I invalidate the getUser query?
api.ts:
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: REACT_APP_API_URL,
prepareHeaders: (headers, { getState }) => {
headers.set('Accept', 'application/json');
const token = (getState() as RootState).auth.token;
if (token) {
headers.set('Authorization', token);
}
return headers;
},
}),
tagTypes: [
'UserGet',
'UserPost',
],
endpoints: () => ({}),
});
userGetApi.ts:
const userGetApi = api.injectEndpoints({
endpoints: (builder) => ({
getUserData: builder.query<UserData, void>({
query: () => '/users/me',
providesTags: ['UserGet'],
}),
}),
overrideExisting: true,
});
export const { useGetUserDataQuery } = userGetApi;
userPostApi.ts:
const userPostApi = api.injectEndpoints({
endpoints: (builder) => ({
saveUser: builder.mutation<void, OnboardingEntry>({
query: (userEntries) => {
const formData = Object.keys(userEntries).reduce((formData, key) => {
formData.append(key, userEntries[key].toString());
return formData;
}, new FormData());
return {
url: '/users/update',
method: 'POST',
body: formData,
};
},
invalidatesTags: ['UserGet'],
}),
}),
overrideExisting: true,
});
export const { useSaveUserMutation } = userPostApi;
The 2 hooks I call:
const { data: { data } = {}, isLoading, isError, isSuccess } = useGetUserDataQuery();
const [saveUser, { isLoading: postIsLoading, isSuccess: postIsSuccess }] = useSaveUserMutation();
After calling saveUser(...), I get redirected to another page. When I revisit the page, I expect to see the updated user data from useGetUserDataQuery(), but I see the previous data. Even when I close and reopen the app, I still get the old data!
So what am I doing wrong here? I'm using 'ProvidesTags' & 'InvalidatesTags' as stated in the docs.
So after days of pure frustration I found the solution: Api headers.
baseQuery: fetchBaseQuery({
baseUrl: REACT_APP_API_URL,
prepareHeaders: (headers, { getState }) => {
headers.set('Accept', 'application/json');
headers.set('Cache-Control', 'no-cache');
headers.set('Pragma', 'no-cache');
headers.set('Expires', '0');
const token = (getState() as RootState).auth.token;
if (token) {
headers.set('Authorization', token);
}
return headers;
},
}),
Hopefully this answer will help others as well

TypeError: Cannot read properties of undefined (reading '$router'), what is this error about? How can I fix this?

$Happy New Year! So, I'm setting up a redirect after an authentication token retrieval and I keep getting "TypeError: Cannot read properties of undefined (reading '$router')" in the console and the user is not redirected to the desired page ("/dashboard"). I'm outsourcing the authentication to a dataRequests.user.js file that then goes to a vue component. Thanks in advance. Here is the code:
import common from "./dataRequests.commons";
import { login, inputLogin, inputPassword } from '/src/pages/Index.vue'
let userRequest = {}
userRequest.authenticate = (inputLogin, inputPassword) => {
return new Promise(() => {
let axios = require("axios");
let config = {
method: 'post',
baseURL: common.baseURL + '/auth/login',
headers: {
'Content-Type': 'application/json',
},
data : {
login: inputLogin,
password: inputPassword,
}
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.then(() => this.$router.push(this.$router.redirect || '/dashboard'))
.catch(function (error) {
console.log(error);
//console.log('input login', this.inputLogin)
//console.log('input password', this.inputPassword)
});
console.log('input login', inputLogin)
console.log('input password', inputPassword)
});
}
export default userRequest;
Something like this:
import common from "./dataRequests.commons";
import { login, inputLogin, inputPassword } from '/src/pages/Index.vue'
import axios from 'axios'
import router from 'router'
let config = {
method: 'post',
baseURL: common.baseURL + '/auth/login',
headers: {
'Content-Type': 'application/json',
}
userRequest.authenticate = (inputLogin, inputPassword) => {
const apiClient = axios.create(config)
return new Promise(() => {
apiClient.post(data : {
login: inputLogin,
password: inputPassword,
})
.then(() => router.push...etc

data sent with vuex action return undefined

i'm using axios with vuex, i need to send data with json form to execute post request and add new row with axios, i'm using vuex, when action is trigered it doesn't keep the data and sent it on action, the data json is created on vue componment but don't send it to action to execute axios post :
Action.js:
export const addClassification = ({data}) => {
console.log('data actio:', {data})
axios
.post("/vendor/classification/save", data, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
// commit("ADD_TO_CLASSIFICATION", data);
})
.catch((err) => {
console.log(err);
});
state.js:
export default {
vendorClassificationList: [],
}
page.vue:
<BaseButton
label="Modifier"
classValue="btn-outline-primary"
#click.native="addClassificationData"
/>
data() {
return {
submitStatus: "",
name: this.$route.params.name,
id: this.$route.params.id,
code: this.$route.params.code,
jsonData:[]
};
},
methods: {
...mapActions(["addClassification"]),
addClassificationData() {
this.jsonData = JSON.stringify({
id: null,
name: this.name,
code:this.code,
active:true
})
console.log('json is', this.jsonData)
this.addClassification({
data : this.jsonData
})
},
Actions is Vuex receive the vuex context as the first param, as you can see in the docs.
In other words if you change in Action.js:
addClassification = ( {data}) => {
to
addClassification = (vuexContext, {data}) => {
it should do the trick. You can call the param vuexContext, context, destructure it if needed or call it _ if unused (as in your case), doesn't really matter, as long as it's there.
Your vuex action is wrong. You are missing the context which can use argument restructuring. Also, you probably need to send res.data within the commit instead of res, depending on what are you doing in your mutation.
actions: {
addClassification ({ commit }, payload) {
axios
.post("/vendor/classification/save", payload, {
headers: {
"Content-Type": "application/json",
// withCredentials: true //sent with cookie
Authorization: "Bearer " + Vue.$cookies.get("jwt"),
}
})
.then((res) => {
console.log('res', res)
commit("ADD_TO_CLASSIFICATION", res.data);
})
.catch((err) => {
console.log(err);
})
}
}

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
})
}