I know, or maybe I don't, but some might be scratching their heads like 'Why do you want a reactive object that you can use with Provide/Inject into your Vuex Store?' ... Well because I can and I gotta'...
Okay, DAD jokes aside I have this plugin that implements authentication and once inistalled into the app I do a "caveman style" vuex plugin function to register it into the namespaced User module of my vuex store, by calling a mutation and passing the reactive const object User
, that is wrapped in the reactive
function of Vue 3, as the payload. Now the funny thing is it loses its reactivity once registered into the store while the Provide/Inject still work totally fine :)
Here's some spaghetti:
AuthLink.vue
...
export default defineComponent({
setup() {
const auth = inject("Auth") as IAuthPluginProperties;
async function logInFromLink(
withPopUp = false,
options?: {
redirectLoginOptions?: RedirectLoginOptions;
popupConfigOptions?: PopupConfigOptions;
analytics: undefined;
}
): Promise<void> {
if (withPopUp) return auth.loginWithPopup();
//* Potentially add analytics for how many people logged in with the link, from which page etc.
return await auth.loginWithRedirect(options?.redirectLoginOptions);
}
function logout(logoutOptions?: LogoutOptions): void {
auth.logout(logoutOptions);
}
return {
auth,
logInFromLink,
logout
};
}
});
</script>
Plugin - index.ts
...
export default {
install: async (app: App, options: pluginInstallOptions): Promise<void> => {
app.config.globalProperties.$auth = Plugin.AuthPluginProperties;
app.provide("Auth", Plugin.AuthPluginProperties);
/*
* Could Handle defaulting to.env vars
* & then -> if !env vars throw err
*/
if (options.useStore) {
if (!store.hasModule("User")) {
throw new Error(
"🙈🙉🙊 Something evil is lurking in the shadows...`User` vuex store module has not been registered."
).stack;
}
await vuexPlugin(store, Vue3AuthPlugin.AuthPluginProperties);
...
Plugin - main.ts
...
const state = reactive({
isLoading: false,
isAuthenticated: false,
user: undefined,
popupOpen: false,
error: null
}) as IAuthStateProp;
export const AuthPluginProperties = reactive({
isAuthenticated: computed(() => state.isAuthenticated),
isLoading: computed(() => state.isLoading),
user: computed(() => state.user),
...some more functions passed here
}) as IAuthPluginProperties;
...
store/modules/User/Mutations.ts
import { MutationTree } from "vuex";
import { UserMutations, UserMutationTypes, UserState } from "@/store/types";
import IAuthPluginProperties from "~interfaces/Auth/IAuthPluginProperties";
const mutations: MutationTree<UserState> & UserMutations = {
[UserMutationTypes.INITIALIZE_PLUGIN](state: UserState, payload: IAuthPluginProperties) {
state.User = payload;
}
};
export default mutations;
[EDIT 1]
Forgot to add the code for the "caveman style" vuex plugin function
auth-vuex-plugin.ts
import { AuthVuexPlugin } from "../types";
const plugin: AuthVuexPlugin<Record<string, unknown>> = async (store, payload) => {
try {
await store.dispatch("User/INITIALIZE_PLUGIN", payload);
} catch (err) {
throw new Error(`🙈🙉🙊 Something evil happened... Vuex init failed: ${err}`);
}
};
export default plugin;
Actually achieved what I was after by passing the payload as ToRefs(payload)
as well as typed it with the generic ToRefs provided by Vue like ToRefs<IAuthState>
.
I'm unsure if this is the best way of going about it, but will leave room for anyone to tag along or if I manage to find something better :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.