I feel like this is a really stupid question and I'm missing something really obvious but I'll ask anyway.
I have a Nuxt plugin that injects a function into the Vue instance, but I need to access another injected method (which is injected by a module, buefy) from within my method. Here's the plugin:
import Vue from 'vue'
Vue.prototype.$disp_error = (err) => {
console.error(err)
Vue.$snackbar.open({
duration: 60000,
message: 'Uh oh! Something went wrong. If it keeps happening, please contact us with this error: ' + err.toString(),
type: 'is-danger'
})
}
However it says $snackbar is undefined. I guess I could solve it by using this as a second argument when I call this.$disp_error within my components, and then using the this context to call $snackbar in my method, but I don't really want to use add second argument.
Could someone remind me what I'm missing? Thanks.
Related
in my complex Vue project I am getting this console warning:
[Vue warn]: Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead.
Unfortunately I can not find the reason for this warning just by the above message.
How can I track down the reason for this warning?
Check if your watching an entire route object anywhere in your code. Doing so throws that error (in my case).
Refer this vue documentation on watching routes
Accessing router and current route inside setup
The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change.
Was able to fix this with the suggestion done by Glass Cannon.(https://stackoverflow.com/a/70205284/11787139)
To clarify and maybe help someone else: I was trying to send an Axios request to the server of which the data I sent through was composed of a direct component reference emitted by the component function.
Component
saveItem(){
this.saved = true;
setTimeout( this.resetState, 2500);
this.$emit('saveitem', this)
},
Parent
saveitem(e){
const data = {item : e}
axios.post(target, data, {headers . . .).then((response) => {}
})
The error disappeared when I instead fetched the index of the list item by doing so:
saveitem(e){
let item;
this.items.forEach( function(item, index, array) {
if(item.id == e.id) pointer = item
})
data.item = pointer
axios.post(target, data, {headers . . .).then((response) => {}
})
}
So I was also having this issue, but not for the reasons the accepted answer provided. It was occurring due to my Vuex store. After a lot of digging I discovered the cause was the presence of the "CreateLogger" plugin.
So if you're having this issue and it's not due to you watching an entire route, check if you're using the CreateLogger plugin in Vuex. That might be the culprit.
This happens for me when I pass this to a data object
data() {
return {
updateController: new UpdateController({
reportTo: this
})
}
}
This used to work fine with Vue 2 but causes this error in Vue 3.
Making this modification solved the problem for me.
data() {
return {
updateController: new UpdateController({
reportTo: () => this
})
}
}
I know this might be anti-pattern but I needed to inject partial reactivity to a non-reactive part of a JS library and this was the most not complicated way of achieving this that I can think of.
This happens to me when destructuring a ref without .value.
This was happening to me only in Firefox, and when I removed the Vue Dev Tools extension it stopped. After re-installing Vue dev tools it hasn't come back. Make sure you have the latest version of the Vue Dev Tools for your browser.
So I am coding a VueJS and ElectronJS template which can be found here: https://github.com/dev-aethex/electronjstemplate
My code works something like this,
Inside of my Vue component I access a global pre constructed class called MainProcessInterface and when it's constructed it first checks if vue is compiled for running in a development server. If it's in a dev server it will connect to the dev socket which electrons main process will host if electron is in dev mode and not compiled. This method seems to be working great, I had to use a socket because vue dev server is being loaded into electron via loadURL and so vue has no clue what ipcRenderer is. Inside the main process interface, if vue is compiled it will instead use the ipcRenderer.send() method. This is were the problem was born.
As soon as Vue runs thought the TS code, it sees ipcRenderer.send and freaks out while printing an error to the electron window console saying fs.existsSync does not exist or is defined.
I can't find a way around this. I though maybe i'll split MainProcessInterface into 2 peices, one for ipc and the other for websockets. Although it isn't a very good way, so before implementing it, I would like to know if there is a better more proper way of doing such.
I had a similar issue with React. Are you importing the ipcRenderer object somewhere in your build process? You might want to make sure it references the correct variable. I tried to drop this in as a comment but it wouldn't fit:
//index.html (index.ejs) for me... This is in the main HTML entry point
var IPC = null;
try {
IPC = require('electron').ipcRenderer;
console.log('IPC IS: ' + IPC)
} catch (err) {
console.log('CRICITCAL ERROR: IPC NOT ENABLED')
console.log(err)
IPC = null;
}
Then I initialize off that context in React with a startup here:
setTimeout(()=>{
console.log('----------------HACK FIRED POST REHYDRATE')
window.REDUX_STORE.dispatch(
(dispatch, getState) => {
const _state = getState()
if(window.IPC) {
if(_state.osc && _state.osc.on) {
dispatch( reconnectToEos() )
} else {
dispatch( updateStatus('[OSC Startup: DISCONNECTED]', ))
}
console.log('\t------------ELECTRON')
} else {
//Shut off OSC
dispatch( updateOscKey('on', false) )
dispatch( updateStatus('[WebApp, OSC disabled]', ))
console.log('\t------------WEB')
}
}
)
}, 1000)
Basically I'm using a global variable (window.IPC) to initialize my app so I don't import a bad variable in my build process. I have a fair number of Electron APIs where this alleviates the issues with building via Webpack.
I hope this helps!
I'm having problem to make my Action resolve the promise.
I've read what looks like the most relevant posts.
Returning Promises from Vuex actions
I want to know when my action is finished, then my component can start doing other stuff.
The problem is, the Action never returns the Promise.
myComponent.vue
methods: {
loadUrls() {
this.$store.dispatch('getUrls').then(result => {
console.log("getUrls result", result)
})
},
vuex.js
actions: {
getUrls() {
console.log("getUrls")
return new Promise((resolve) => {
setTimeout(() => {
console.log("setTimeout in")
resolve("Resolved!")
}, 1000)
})
},
That's my console log:
I've used the "setTimeout" to make as simple as possible the problem. In real life I call an API.
I do not need to rely on the result of this promise. I'm aware about it. I use Vuex as the source of truth, but I need to track when the event in completed.
Thanks in advance =)
SOLVED! It worked after I delete my dist Folder, close VSCode and open a new Chrome instance using the new build local host URL.
Thanks #User-28. I saw his shared code and realised nothing was wrong with my code. Then I start looking at my environment.
My very first code didn't have Promise Resolve in the action. I compiled and I was testing it.
Then I found Returning Promises from Vuex actions which explained how to use the Promise in it. I compiled and I was TRYING to test it. Never success. Somehow the code without the Promise was always there. After clean up Dist folder, Close VS code and use a new Chrome instance, the new code was in place and worked.
I'm still don't know the actual problem, but at least it can keep going forward now.
I have an Aurelia app using Aurelia Store. I'm having some trouble when using the #connectTo decorator in an Aurelia pipeline step.
I have added the following step to my config pipeline:
config.addPipelineStep('authorize', AuthorizeStep);
And this step looks like:
#connectTo()
export class AuthorizeStep {
state: State;
run(navigationInstruction, next) {
if (navigationInstruction.getAllInstructions().find(x => x.config.isAdmin))
{
if (!this.state.user.isAdmin) {
return next.cancel();
}
}
return next();
}
}
However, my state is always undefined. Looking at other parts of my project, I can see the state and user are being populated, but it seems like in this AuthorizeStep it doesn't seem to work.
I think this issue may be due to the fact that my AuthorizeStep doesn't have a bind lifecycle method, but if so, what can I do about this?
The maintainers of Aurelia responded (only after I raised an issue on their GitHub) here.
Basically, as the bind lifecycle does not exist within this class, the #connectTo decorator won't work. Instead, I will need to manually inject the Store and subscribing to the state.
In my Vuex setup, the store is currently structured like this:
store
- modules
- common_data
- index.js
- mutations.js
- actions.js
- getters.js
Now, one of the actions inside actions.js is defined as:
populateTimeZones(context) {
var baseUrl = context.getters.getApiBaseUrl;
this.$http.get(baseUrl + '/time-zones')
.then(function (res){
if(res.status == 'ok'){
this.$store.commit('SET_TIME_ZONES', res.info.timeZones);
} else {
alert('An error occurred. Please try again!');
return;
}
}.bind(this));
}
I think the Vue instance is not available here, which is causing the action to fail with the error: Cannot read property 'get' of undefined. I've tried other combinations like this.axios and vue.axios but the result is same.
Am I doing something wrong? What is the common pattern for handling such cases?
You won't be able to access the Vue instance without passing it through or creating a new one.
A simple way to do what you want is to simply pass your this through to your action this.$store.dispatch('populateTimeZones', this), then change your method signiture to populateTimeZones({ context }, vueInstance). This would then allow you to access vueInstance.$http.
Another idea would be something called vue-inject which is a DI container for Vue. It would allow you to register axios as a service and then simply call VueInjector.get('axios') whenever you need it. On the Vue component itself you can do dependencies: ['axios'] and then use like this.axios. Not so much an issue in this case but helpful when you have lots of services doing work for you