Vue Composition API from outside of Vue - javascript

So, I've started using the Vue Composition API, and it's brilliant. I'm using it in a project that has Vue components, but also Vanilla JS. I'm building a notification system in Vue, as we are slowly moving everything that way.
I have the following code currently for adding a notification
export const useNotification = () => {
const notifications = ref([]);
const visibleNotifications = computed(() => {
return notifications.value.filter(notification => notification.visible === true).reverse();
});
const add = (notification: Notification) => {
notifications.value.push(notification);
};
};
I can get this adding perfectly from within Vue, but I want to also add a notification from the vanilla JS parts of the system. I've tried using useNotification().add() but I get the following error [vue-composition-api] must call Vue.use(plugin) before using any function. Basically, it wants me to use it inside Vue.
Any ideas on how I get this working?

Due to the shortcomings of using the vue-composition-api with vue2, and following the SO question here, I needed to add the following to type of my exported TS file
import Vue from 'vue';
import VueCompositionApi from '#vue/composition-api';
Vue.use(VueCompositionApi);

Related

Can't call custom hook from custom hook in react

I have a React app created with create-react-app.
I'm trying to make a custom hook using Microsoft Authentication Library (MSAL). MSAL has a custom React hook that I want to call from my own custom hook.
When I use a hook (any hook) inside my custom hook in a separate file I get this in the browser:
Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
// ourhook/index.ts
import { useEffect } from "react";
export const useMsal2 = () => {
useEffect(() => {
console.log("Hello from our hook!");
});
};
// app.tsx
import React from "react";
import { useMsal2 } from "./ourhook";
const App = () => {
useMsal2();
return <div>App</div>;
};
export default App;
If I call
const { instance } = useMsal();
directly from App.tsx everything works fine. It only appears to be a problem if my custom hook is in its own file.
From what I see I'm not violating any hook rules. I'm calling a hook that's calling a hook, and the first call is from a top level component.
I have read other threads here about hooks in hooks, but none of them has an answer that fits this problem.
Have I missed something about hook rules, or what might be causing this?
Okay, I forgot that we tried to have /ourhook as a freestanding project and then copy pasted it into a create react app app.
Some of you were right, it did have its own version of react.
I'm just going to hide under a rock for the rest of the week.
Thanks for all your help! <3
Try to add this comment just above:
import { useMsal } from "#azure/msal-react";
export const useMsal2 = () => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const { instance } = useMsal();
const request = "";
return {
loginRedirect: () => console.log(""),
}
};
I don't know what useMsal looks like, but from what I see, you don't actually violate any hook rule.

Next JS dynamic import for named export

I am learning next js. I want to call a function getItem of https://www.npmjs.com/package/encrypt-storage
Using below code, but I am getting TypeError: EncryptStorage.getItem is not a function
import dynamic from 'next/dynamic';
const EncryptStorage = dynamic(() => import('encrypt-storage').then((mod) => mod.EncryptStorage(process.env.NEXT_PUBLIC_SKK)), { ssr: false });
console.log(EncryptStorage.getItem('aa'));
please help me to sort it out.
tl;dr: You need to use await import(...) instead of dynamic(() => import(...)) as the latter is only for components.
The longer version:
This was confusing to me as well as the docs don't outright state that you can't import modules with dynamic(...), only that it should be used to import components:
React components can also be imported using dynamic imports, but in this case we use it in conjunction with next/dynamic to make sure it works just like any other React Component.
And indeed, looking at this comment from a maintainer you can't use dynamic(...) to import modules, only components.
Given this, here's a possible solution:
Also, note that .getItem(...) is a method that needs to be called on an instance of EncryptStorage.
// Needs to be ran in an `async` context or environment that supports top-level `await`s
const EncryptStorage = (await import("encrypt-storage")).default;
const encryptStorage = EncryptStorage(process.env.NEXT_PUBLIC_SKK);
console.log(encryptStorage.getItem("aa"));
And, here's a sandbox with a full working example.

How to use Vue2 plugins on Vue3 Composition API?

I am migrating my Vue2 App to use #vue/composition-api (Vue version still 2 not 3).
In Vue2 I use my plugins like this.$session however this won't work on Vue3. The solution I found was to use like this:
setup (props, context) {
context.root.$session // works fine
context.root.$anotherPlugin
}
However in Vue3 context.root is #deprecated so when I migrate to Vue3 it will not work anymore.
Is there any other way to access Vue instance inside setup()? I think if I could access it I can use those plugins normally on Vue3.
Use provide & inject
Provide
const app = createApp(App);
app.provide('someVarName', someVar); // Providing to all components here
Inject:
const { inject } = Vue;
...
setup() {
const someVar = inject('someVarName'); // injecting in a component that wants it
}

Making a classic javascript 3rd party app work within an existing react/node app

I have an app that does video chat already built in react/node.
I am trying to add a feature that opens up a shared whiteboard that the participants in the video chat can use.
I did some research and AwwApp is the one I like the best for this shared whiteboard functionality.
AwwApp does not have react specific code examples or modules. However, they do provide a straightforward widget that uses a .js file they host.
I am trying to implement this classic javascript widget into my existing react app and running into some issues - likely due to something simple that I'm just missing.
Here's the simple AwwApp quick start with the js file to include and how to call it the classic way: https://awwapp.com/apis/V2/docs/
Here is the code from my "AwwBoard.js" file that I am using to create a component that renders the whiteboard anywhere I want to import it and return in react:
import React, { Component } from 'react';
import Cookies from 'universal-cookie';
import Script from 'react-load-script'
// Get cookie for meeting room that this whiteboard instance will appear in. Will be used after I get whiteboard working.
const cookieMgr = new Cookies();
const room = cookieMgr.get('room');
// The main AwwApp external javascript file to include, I use react-load-script to load it below
const awwAppScript = 'https://awwapp.com/static/widget/js/aww3.min.js';
// Create a React component I can display using <AwwBoard /> anywhere I want a whieboard to appear
class AwwBoard extends Component {
handleScriptCreate() {
this.setState({ scriptLoaded: false });
};
handleScriptError() {
this.setState({ scriptError: true });
};
handleScriptLoad() {
this.setState({ scriptLoaded: true });
};
// Function I created to render the board. Per https://awwapp.com/apis/V2/docs/ - should embed the whiteboard widget in the div with id aww-wrapper below
handleBoardRender() {
var aww = new AwwBoard('#aww-wrapper', {
});
return aww;
};
render() {
return (
<div id="aww-wrapper">
<Script
url={awwAppScript}
onCreate={this.handleScriptCreate.bind(this)}
onError={this.handleScriptError.bind(this)}
onLoad={this.handleScriptLoad.bind(this)}
/>
{this.handleBoardRender()}
</div>
)
};
};
export default AwwBoard;
Any guidance would be greatly appreciated. I'm sure there is an easy way to do this, I'm just not seeing it after doing some of my own trial and error.
Thanks!

Is there a way to import rxjs into a plain js web custom component?

I'm trying to create web custom components using plain js. I would like to use rxjs and observables to fetch json content from a REST endpoint that I am also creating using python pyramid. However, an error - 'TypeError: global is undefined' - is being thrown when I import rxjs.
import 'https://unpkg.com/#reactivex/rxjs#6.0.0/dist/global/rxjs.umd.js';
also tried:
import 'https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.js';
I would like to NOT use npm at all.
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.js"></script>
then:
const { Observable, from } = rxjs;
With NodeJS and plain JS:
<script src="node_modules/rxjs/dist/bundles/rxjs.umd.js"></script>
// And JS code sample...
this.networkStatus$ = rxjs.merge(
rxjs.of(null),
rxjs.fromEvent(window, 'online'),
rxjs.fromEvent(window, 'offline')
)
this.applicationStatus$ = new rxjs.BehaviorSubject(this.getApplicationStatus());

Categories

Resources