I would like to be able the same axios instance used in the auth module (https://auth.nuxtjs.org/) in a javascript module where I make my API calls
I have the following
const BASE_URL = 'job';
export default {
getJobs(params?: Filter) {
return axios.get(BASE_URL, { params });
},
getJob(slug: string, params?: Filter) {
return axios.get(`${BASE_URL}/${slug}`, { params });
}
}
I would like to be able to use the same $axios instance inside of this js module. Something like:
const BASE_URL = 'job';
export default {
getJobs(params?: Filter) {
return this.$axios.get(BASE_URL, { params });
},
getJob(slug: string, params?: Filter) {
return this.$axios.get(`${BASE_URL}/${slug}`, { params });
}
}
Is this possible?
Yes it is possible to get axios instance using this.$axios in Nuxt.js
Related
How do I set the baseURL that is used in useFetch composable globally (maybe nuxt.config.ts) so that I wouldn't have to define it in every useFetch.
You can define the baseURL in your nuxt.config.js|ts like this:
import { defineNuxtConfig } from 'nuxt'
export default defineNuxtConfig({
// ...
runtimeConfig: {
public: {
baseURL: process.env.BASE_URL || 'https://api.example.com/',
},
},
// ...
(or use a fixed value or only the environment variable - as you like)
And add this composable:
// /composables/useMyFetch.js
export const useMyFetch = (request, opts) => {
const config = useRuntimeConfig()
return useFetch(request, { baseURL: config.public.baseURL, ...opts })
}
If you want to have the full blown version with types it's a bit longer:
// /composables/useMyFetch.ts
import { UseFetchOptions } from '#app'
import { NitroFetchRequest } from 'nitropack'
import { KeyOfRes } from 'nuxt/dist/app/composables/asyncData'
export function useMyFetch<T>(
request: NitroFetchRequest,
opts?:
| UseFetchOptions<
T extends void ? unknown : T,
(res: T extends void ? unknown : T) => T extends void ? unknown : T,
KeyOfRes<
(res: T extends void ? unknown : T) => T extends void ? unknown : T
>
>
| undefined
) {
const config = useRuntimeConfig()
return useFetch<T>(request, {
baseURL: config.public.baseURL,
...opts,
})
}
You can then use useMyFetch as replacement for useFetch - but with baseURL being set :-)
The following composable could be set
/composables/useJsonP.ts
export const useJsonP = async (path) => {
return await useFetch(() => `https://jsonplaceholder.typicode.com/${path}`)
}
And you could call this in your view
<script setup>
const jsonP = await useJsonP('todos/1')
</script>
<template>
<div>
<pre>{{ jsonP.data }}</pre>
</div>
</template>
That way, no need to define it somewhere and hack somehow the configuration. You do have a simple way of defining reusable pieces of code, that are directly imported into your components/views thanks to the DX of Nuxt.
For anyone still looking for the answer to the original question you can do this in nuxt.config with runtimeConfig and env variables. You can of course replace the env variables with a hard-coded values if you prefer.
In your nuxt.config.js/ts
runtimeConfig: {
SOME_SECRET_KEY: process.env.SOME_SECRET_KEY,
public: {
SOME_API_KEY: process.env.SOME_API_KEY,
},
},
Then in someComposable.js:
const config = useRuntimeConfig();
You can then access your variables as eg config.public.SOME_API_KEY
Hope that helps. More info here: https://v3.nuxtjs.org/guide/features/runtime-config
You can also involve .env like this
in .env
NUXT_PUBLIC_BASE_URL = https://www.someapi.com
in nuxt.config.js/ts
runtimeConfig: {
public: {
BASE_URL: 'some fallback value',
},
},
as it said in the document BASE_URL will be replaced by NUXT_PUBLIC_BASE_URL automatically
( no need to use process.env.NUXT_PUBLIC_BASE_URL )
and in composable you can use
const config = useRuntimeConfig();
console.log('base url is' , config.baseUrl)
I'm having some issues finding a clean way of returning results from inside a method to my template using Apollo v4 and Vue 3 composition API.
Here's my component:
export default {
components: {
AssetCreationForm,
MainLayout,
HeaderLinks,
LoadingButton,
DialogModal
},
setup() {
const showNewAssetModal = ref(false);
const onSubmitAsset = (asset) => {
// how do I access result outside the handler function
const { result } = useQuery(gql`
query getAssets {
assets {
id
name
symbol
slug
logo
}
}
`)
};
}
return {
showNewAssetModal,
onSubmitAsset,
}
},
}
The onSubmitAsset is called when user clicks on a button on the page.
How do I return useQuery result from the setup function to be able to access it in the template? (I don't want to copy the value)
You can move the useQuery() outside of the submit method, as shown in the docs. And if you'd like to defer the query fetching until the submit method is called, you can disable the auto-start by passing enabled:false as an option (3rd argument of useQuery):
export default {
setup() {
const fetchEnabled = ref(false)
const { result } = useQuery(gql`...`, null, { enabled: fetchEnabled })
const onSubmitAsset = (asset) => {
fetchEnabled.value = true
}
return { result, onSubmitAsset }
}
}
demo
so I'm trying to get my Axios to do a get request with a param that'll end the url in
'/?user= {id}'
the id is passed in by my loggedInUser.id from Vuex. I know that async functions won't accept 'this' inside the call so I included store as a parameter. Something's still off with how I passed the data around thought I think. Would appreciate any help, thanks!
import { mapGetters } from "vuex";
export default {
computed: {
...mapGetters(["loggedInUser"])
},
head() {
return {
title: "Actors list"
};
},
components: {
EditProfile
},
async asyncData({ store }) {
try {
const body = { data: store.getters.loggedInUser.id };
const { actors } = await $axios.$get(`/api/v1/actors/`, {
params: {
user: body
}
});
return { actors };
} catch (e) {
return { actors: [] };
}
},
data() {
return {
actors: []
};
Edit
I got it to work when I removed the data: from 'const body' and removed the brackets as well around 'actor'
try {
const body = store.getters.loggedInUser.id;
const actors = await $axios.$get(`/api/v1/actors/`, {
params: {
user: body
}
});
You can access your params from Context.
Context is available in special nuxt lifecycle areas like asyncData, fetch, plugins, middleware and nuxtServerInit.
In Nuxt, with asyncData hook you can get query parameters from the route context key.
Please read the Nuxt.js Context documentation. The context provides additional objects/params from Nuxt to Vue components
With your-domain/?user=wonderman
asyncData({ route: { query: queryParams} }) {},
variable queryParams is an object:
{ user: "wonderman" }
I am using Nuxt.js and want to test my page which uses asyncData with Jest. I have a factory function to set up my wrapper, but it basically returns a shallowMount.
Expected
When clicking a button I want the function to behave differently depending on the query parameter. When running the test I want to mock this by setting it directly when creating the wrapper (Similar to setting propsData). E.g. const wrapper = factory({ propsData: { myQueryParam: 'some-value' } });
Result
However trying to set propsData still returns undefined: console.log(wrapper.vm.myQueryParam); // undefined while I would expect it to be 'some-value'
Question
Is there a different approach on how I can test this function that relies on query parameters?
Because asyncData is called before Vue is initialised, it means shallowMount doesn't work right out of the box.
Example:
page:
<template>
<div>Your template.</div>
</template>
<script>
export default {
data() {
return {}
},
async asyncData({
params,
error,
$axios
}) {
await $axios.get("something")
}
}
</script>
test:
import { shallowMount } from "#vue/test-utils";
describe('NewsletterConfirm', () => {
const axiosGetMock = jest.fn()
const axiosPostMock = jest.fn()
var getInitialised = async function (thumbprint) {
if (thumbprint == undefined) throw "thumbprint not provided"
let NewsletterConfirm = require('./_thumbprint').default
if (!NewsletterConfirm.asyncData) {
return shallowMount(NewsletterConfirm);
}
let originalData = {}
if (NewsletterConfirm.data != null) {
originalData = NewsletterConfirm.data()
}
const asyncData = await NewsletterConfirm.asyncData({
params: {
thumbprint
},
error: jest.fn(),
$axios: {
get: axiosGetMock,
post: axiosPostMock
}
})
NewsletterConfirm.data = function () {
return {
...originalData,
...asyncData
}
}
return shallowMount(NewsletterConfirm)
}
it('calls axios', async () => {
let result = await getInitialised("thumbprint")
expect(axiosGetMock).toHaveBeenCalledTimes(1)
});
});
Credits to VladDubrovskis for his comment: in this nuxt issue
I have a repository (in a MenuRepository.js file) that has an index() method, when I try to call that method from my mounted() function in my Vue instance, I get the following error
This has been working before, So I can't imagine what happened..
This is the code of my Vue instance.
class MenuRepository {
async index () {
const result = await Nova.request().get('/')
return result.data
}
}
export default MenuRepository
And this is the Vue file
import MenuRepository from '../repositories/MenuRepository'
export default {
async mounted () {
try {
const menus = await MenuRepository.index()
} catch (err) {
console.error(err)
}
}
}
Solution
The issue was that it wasn't being instantiated.
Use
export default new MenuRepository()
Instead of
export default MenuRepository