Webpack Imported Module is not a function - vue.js

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

Related

This dependency was not found: #/services/AuthenticationService

I'm trying to use my AuthentifcationService in a Vue.js component
This dependency was not found:
* #/services/AuthenticationService in ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/Register.vue
To install it, you can run: npm install --save #/services/AuthenticationService
Path structure: src->services.
AuthenticationService.js:
import Api from '#/services/Api'
export default {
register (credentials) {
return Api().post('register', credentials)
}
}
Register.vue
<script>
import AuthenticationService from '#/services/AuthenticationService'
export default {
data () {
return {
email: '',
password: ''
}
},
methods: {
async register () {
const response = await AuthenticationService.register({
email: this.email,
password: this.password
})
console.log(response.data)
}
}
}
</script>
Looks like you trying to use your function from AuthenticationService. But you can´t use it like a class and if you want to use it with mixins, you can´t call a function in your component the same name, as it would be overwritten.
As a mixin, you could import it like that:
import AuthenticationService from '#/services/AuthenticationService'
data () {
return {
mixins: [AuthenticationService]
}
}
Then you just call register. But note that if you import a function named register with mixins and there is also a function in your component named register, the imported function gets overwritten.

Use $axios in a module in Nuxt

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

How to set mock nuxt asyncData in jest

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

Nuxt access store (in Module mode) from JS file

I have an AuthService that I use in a namespaced store in my Nuxt app. I need to commit mutations from AuthService to the namespaced store but I can't figure out how to import the store into my AuthService.
I've seen examples where the store is imported into the JS file, but the store is explicitly defined in the Vue app. Because I'm using Nuxt with the Module mode for my store, I'm not sure of the root path where I can import my store into the AuthService file. As I understand it, Nuxt handles creating the root store and all the namespaced store behind the scenes when use "Module mode"
My Nuxt store directory includes index.js (which is empty) and auth.js which has the mutations I want to call from AuthService.
auth.js
import AuthService from '../firebase/authService'
const authService = new AuthService()
export const state = () => ({
user: null
})
export const mutations = {
setUser (state, user) {
state.user = user
}
}
export const actions = {
async signUp ({ commit }, payload) {
try {
await authServices.createUser(payload)
return Promise.resolve()
} catch (err) {
const notification = {
duration: 5000,
message: err.message,
type: 'error'
}
commit('ui/activateNotification', notification, { root: true })
return Promise.reject()
}
}
}
authService.js
import { fAuth, fDb } from './config'
// I think I need to import auth store here but I'm not sure how
export default class AuthClient {
async createUser (payload) {
try {
const res = await fAuth.createUserWithEmailAndPassword(payload.email, payload.password)
const { uid } = res.user
const user = {
...payload,
uid
}
await this._createUserDoc(user)
this._initAuthListener()
return Promise.resolve()
} catch (err) {
return Promise.reject(err)
}
}
async _createUserDoc (user) {
await fDb.collection('users').doc(user.uid).set(user)
}
_initAuthListener () {
fAuth.onAuthStateChanged(async (user) => {
try {
if (user) {
const userProfileRef = fDb.collection('users').doc(user.uid)
const userProfileDoc = await userProfileRef.get()
const { uid, userName } = userProfileDoc.data()
// Here is where I want to call a mutation from the auth store
this.store.commit('setUser', {
uid,
userName
})
} else {
this.store.commit('setUser', null)
}
} catch (err) {
console.log(err)
}
})
}
}
I'd like to propose a solution using a plugin.
In the external module (externalModule.js) we define store variable and export an init function that receives Nuxt context as argument. The function assignes the store from context to the variable which can be now used in the module:
let store;
export function init (context) {
store = context.store;
};
(...further business logic using store)
Then in the plugins folder we create a plugin file (let's call it storeInit.js). The file imports the init function from the external module and exports default plugin function required by Nuxt. The function receives context from Nuxt and we call the init function passing the context further:
import { init } from '[pathTo]/externalModule.js';
export default (context, inject) => {
init(context);
};
Then we register the plugin in the nuxt.config.js file:
module.exports = {
...
plugins: [
{ src: '~/plugins/storeInit' }
],
...
}
This way when the app is built by Nuxt and plugins are registered, the context object is passed to the external module and we can use anything from it, among others the store.
In index.js file which is in store folder you need to return store like this
import Vuex from 'vuex'
const createStore = () => {
return new Vuex.Store({
state: {
counter: 0
},
mutations: {
increment (state) {
state.counter++
}
}
})
}
export default createStore
and in your authService.js file you need to import store like this
import $store from '~/store'
by this you will be able to access your store
$store.commit('setUser', null)
I hope this works for you
Important Note: you don't need to install vuex because it is already shipped with nuxtjs
You can access as window.$nuxt.$store
Note: My nuxt version is 2.14.11

Vuejs - Can I use an imported function in my global router.beforeEach

I am trying to use an imported function in my global router guard. But I'm getting this error:
getCurrentStage is not defined
getCurrentStage is imported from shops.js
shop.js looks like this
import axios from 'axios'
export function getCurrentStage() {
axios.get("/admin/wine_app/shops").then(response => {
return response.data.current_stage;
});
}
export default getCurrentStage
I then import it like this: import getCurrentStage from '../api/shops'
And then try and use it like this in my global router guard:
router.beforeEach((to, from, next) => {
if(to.name == null){
let current_stage = getCurrentStage();
}
else {
next();
}
})
But I get the not defined error. Any help?
You haven't returned anything in the exported function. You need to return the axios promise so that current_stage has something returned to it:
export function getCurrentStage() {
return axios.get("/admin/wine_app/shops").then(response => {
return response.data.current_stage;
});
}
That's just going to return the promise so you'll need to do some appropriate async stuff like await or .then with that promise. For example:
getCurrentStage().then(stage => {
current_stage = stage;
});
You're also exporting the function twice which is probably not intentional. You don't need the first export if you only plan to retrieve it by importing the default.