Hi I tried to use actioncable-vue on vue3 project, https://github.com/mclintprojects/actioncable-vue, the problem with me that I can not use this.$cable on vue 3 setup. It always show undefined errors. Anyone know how to use $cable on vue setup, I dont want use methods on vue2.
setup () {
const subscible = () => {
this.$cable.perform({
channel: 'ChatChannel',
action: 'send_message',
data: {
message: { message, chat_id: chatId.value, receiver_id: receiverId }
}
})
}
}
Related
I have created a custom hook that returns the translated value using the useTranslation hook.
import { useTranslation } from "next-i18next";
export const useCustomHook = (data) => {
const {t, i18n: { language: locale }} = useTranslation();
const value = {
field: t("some.key.from.json.file", { arg: data.arg }),
field2: data.name,
field3: t("another.key", {
arg: data.arg2, count: 3
})
}
return value;
};
I want to create a unit test for this custom hook, but I can't get the useTranslation hook to work as it does when running the app itself. Further info my current setup is as follows:
1- I'm using Nextjs with next-i18next library.
2- No i18n provider to wrap the app, only using HOC from next-i18next to wrap _app.
3- I have 2 json files for locales.
Is there a way to allow the useTranslation hook to work and get the parsed value from the translation file? here's what I tried so far too:
1- mocking the useTranslation hook, but this returns the ("another.key") as is without the parsed value.
2- I tried to create a wrapper with i18n-next provider, but that didn't work too.
Here's my test file.
describe("useCustomHook()", () => {
it("Should return correctly mapped props", () => {
const { result } = renderHook(() =>
useCustomHook(mockData)
);
const data = result.current[0];
expect(data.field).toBe(mockData.field); // this returns ("some.key.from.json.file") it doesn't use the t function,
// ... //
});
I have a Vue 3 app and an express server. The server does not serve any pages just acts as an API so no socket.io/socket.io.js file is sent to client.
I am trying to set up socket.io in one of my vue components but whatever I try does not work. Using vue-3-socket.io keeps giving 't.prototype is undefined' errors.
I have tried vue-socket.io-extended as well with no luck.
Any advice would be appreciated as to the reason and solution for the error above, I have tried various SO solutions without success, and the best way forward.
You can use socket.io-client. I have used socket.io-client of 4.4.1 version.
step: 1
Write class inside src/services/SocketioService.js which returns an instance of socketio.
import {io} from 'socket.io-client';
class SocketioService {
socket;
constructor() { }
setupSocketConnection() {
this.socket = io(URL, {
transports: ["websocket"]
})
return this.socket;
}
}
export default new SocketioService();
Step 2:
Import SocketioService in App.vue. You can instantiate in any lifecycle hook of vue. I have instantiated on mounted as below. After instantiation, I am listening to welcome and notifications events and used quasar notify.
<script>
import { ref } from "vue";
import SocketioService from "./services/socketio.service.js";
export default {
name: "LayoutDefault",
data() {
return {
socket: null,
};
},
components: {},
mounted() {
const socket = SocketioService.setupSocketConnection();
socket.on("welcome", (data) => {
const res = JSON.parse(data);
if (res?.data == "Connected") {
this.$q.notify({
type: "positive",
message: `Welcome`,
classes: "glossy",
});
}
});
socket.on("notifications", (data) => {
const res = JSON.parse(data);
let type = res?.variant == "error" ? "negative" : "positive";
this.$q.notify({
type: type,
message: res?.message,
position: "bottom-right",
});
});
},
};
</script>
In vue 2+ I can easily get the instance of this as a result I can write something like this,
// main.js
app.use(ElMessage)
// home.vue
this.$message({
showClose: true,
message: 'Success Message',
type: 'success',
})
What should I do for vue 3 as,
Inside setup(), this won't be a reference to the current active
instance Since setup() is called before other component options are
resolved, this inside setup() will behave quite differently from this
in other options. This might cause confusions when using setup() along
other Options API. - vue 3 doc.
Using ElMessage directly
ElementPlus supports using ElMessage the same way as $message(), as seen in this example:
import { ElMessage } from 'element-plus'
export default {
setup() {
const open1 = () => {
ElMessage('this is a message.')
}
const open2 = () => {
ElMessage({
message: 'Congrats, this is a success message.',
type: 'success',
})
}
return {
open1,
open2,
}
}
}
Using $message()
Vue 3 provides getCurrentInstance() (an internal API) inside the setup() hook. That instance allows access to global properties (installed from plugins) via appContext.config.globalProperties:
import { getCurrentInstance } from "vue";
export default {
setup() {
const globals = getCurrentInstance().appContext.config.globalProperties;
return {
sayHi() {
globals.$message({ message: "hello world" });
},
};
},
};
demo
Note: Being an internal API, getCurrentInstance() could potentially be removed/renamed in a future release. Use with caution.
Providing a different method where the idea is to set a globally scoped variable to the _component property of the viewmodel/app or component:
pageVM = Vue.createApp({
data: function () {
return {
renderComponent: true,
envInfo: [],
dependencies: [],
userGroups: []
}
},
mounted: function () {
//Vue version 3 made it harder to access the viewmodel's properties.
pageVM_props = pageVM._component;
this.init();
},
Hi everyone here is the mixin code I wrote as I want to use this for default.vue and error.vue layout. I am trying to avoid duplicating code in two layout.
export default {
provide () {
return {
copyRight: this.getCopyrightText,
email: this.getEmail,
socials: this.getSocials
}
},
computed: {
getMenu () {
return this.store.getters['general/getMenu'].menu
},
getSocials () {
return this.store.getters['general/getSocialDetails']
},
getCopyrightText () {
return this.store.getters['general/getCopyRight']
},
getEmail () {
return this.store.getters['general/getEmail']
}
},
middleware: 'load-menu-items'
}
This is what I get: Cannot read property 'length' of undefined
What am I doing wrong?
In your component I assume you're using .length on the data you're receiving from the getter method, which is probably where the error occurs.
First of all you should debug to see if your getter is actually working as expected. Try this and look at output in console for every getter computed property. If undefined is printed to the console you'll get the error you posted if you're using .length on it
getEmail () {
let data = this.store.getters['general/getEmail'];
console.log(data);
return data;
}
If you post the component which is using this mixin maybe I can help you further.
Im using VueJS and Vuex. I have the userid into the store, this way:
vuex screenshot
And i try pass the userid to a fetch, but vuejs return error
([Vue warn]: Error in created hook: "TypeError: this.$store is
undefined")
import { LOAD_APPOINTMENTS } from './types'
export default {
loadProducts ({ commit }) {
var user = this.$store.state.user.userid
fetch('api/appointments/' + user)
.then((result) => {
return result.json()
})
.then((appointments) => {
commit(LOAD_APPOINTMENTS, appointments)
})
.catch(er => {
console.log(er)
})
}
}
First, when referencing the store within vuex files:
context.state instead of this.$store.state.
context for all of the this.$store. So, context.commit and context.dispatch.
Second, the loadProducts needs to be rewritten as an action per docs.
Third, loadProducts needs to incorporate the context as a parameter:
actions: {
loadProducts (context) {
...
context.commit(...)
...
}
}
As #phil has mentioned in this thread, it is important to view the documentation entirely, as this single answer will get you on the way to debugging the problem, but there might be multiple more problems showing up (e.g. fetch errors, file structure errors, component/App level errors).