I'm trying to implement a audio player with subtitle synchronization in my vue app.
I found a pen by #Musixmatch which does the work.
However, its all vanilla.
In my vue app, I created a lyric.js file which contains the js code enclosed by:
export const initAudioSub = () => {
return new Promise(resolve => {
....the vanillajs code here...
})
}
Now in my component.vue, I imported it like this import { initAudioSub } from './lyric.js'
and called the initAUdioSub in the mounted hook like this mounted() { initAudioSub(); }
but I get an error saying :
Uncaught (in promise) ReferenceError: $ is not defined
at eval (lyric.js?6080:4)
Am I even close? can someone enlighten me on how to do it?
Related
I have a component that uses React.Children internally to do some changes to the children components when rendering it. When I try to test it using Jest and React Testing Library, I get the error TypeError: Cannot read properties of undefined (reading 'Children'), and it points to the line where I'm using React.Children.map.
I tried to write a simple component to see if it was a problem on the more complex component, but it seems to be happening as well. Here's the test component I created:
import React from 'react';
export default function Testing({ children }) {
return <div>{React.Children.map(children, (child) => child)}</div>;
}
And here's the test:
import { render } from '#testing-library/react';
import Testing from './Testing';
describe('Home', () => {
it('should render successfully', () => {
const { baseElement } = render(<Testing>Testing</Testing>);
expect(baseElement).toBeTruthy();
});
});
And here's the returned error:
detail: TypeError: Cannot read properties of undefined (reading 'Children')
at Testing (/Users/user/projects/my-project/src/features/Home/Testing.tsx:4:22)
I tried importing React into the test to see if it would make a difference, but I doesn't. I also tried to look for this on both Jest and React Testing Library docs, but I couldn't find anything. I also couldn't find references to this problem on the internet, which is a bit strange as I believe I'm not the first one who's testing components that uses React.Children internally.
Any help would be welcomed! Thanks!
Its because children is undefined. Try by using React?.Children?.map(children, (child) => child)in your code
I'm still a beginner in Nextjs, trying to implement a simple javascript like:
document.addEventListener("scroll", function () {console.log("scroll!")})
how to add the function in a local file and then load it with <script/> in nextjs ?
P.S: i made a .js file with the function inside inside the project folder and tried to load it with next Script component but it gives me this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
Next.js works with Modulation system.
If you want to add this function in some file, you need to export this function.
The code of the external file, let's call it "externalFile.js"
export function addScrollEventListener() {
document.addEventListener("scroll", function () {console.log("scroll!")})
}
Then when you want to use it in your component, you need to import it.
import { addScrollEventListener } from './externalFile';
In the useEffect hook ( which executes after mounting ), you can use it.
useEffect(() => { addScrollEventListener() }, [] )
Trying to create an xterm react component in Next.js I got stuck as I'm not able to get over an error message I've never got before.
I'm trying to import a npm client-side module called xterm, but if I add the import line the application crashes.
import { Terminal } from 'xterm'
The error reads Server Error... ReferenceError: self is not defined
and then shows this chunk of code as Source
module.exports = require("xterm");
According to some research I did, this has to do with Webpack and could be helped if something like this was done:
output: {
globalObject: 'this'
}
Would you know how to fix this?
The error occurs because the library requires Web APIs to work, which are not available when Next.js pre-renders the page on the server-side.
In your case, xterm tries to access the window object which is not present on the server. To fix it, you have to dynamically import xterm so it only gets loaded on the client-side.
There are a couple of ways to achieve this in Next.js.
#1 Using dynamic import()
Move the import to your component's useEffect, then dynamically import the library and add your logic there.
useEffect(() => {
const initTerminal = async () => {
const { Terminal } = await import('xterm')
const term = new Terminal()
// Add logic with `term`
}
initTerminal()
}, [])
#2 Using next/dynamic with ssr: false
Create a component where you add the xterm logic.
// components/terminal-component
import { Terminal } from 'xterm'
function TerminalComponent() {
const term = new Terminal()
// Add logic around `term`
return <></>
}
export default TerminalComponent
Then dynamically import that component when using it.
import dynamic from 'next/dynamic'
const TerminalComponent = dynamic(() => import('<path-to>/components/terminal-component'), {
ssr: false
})
As an alternative, you could add the logic directly when dynamically importing the library with next/dynamic to avoid having an extra file for it.
import dynamic from 'next/dynamic'
const Terminal = dynamic(
{
loader: () => import('xterm').then((mod) => mod.Terminal),
render: (props, Terminal) => {
const term = new Terminal()
// Add logic with `term`
return <></>
}
},
{
ssr: false
}
)
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);
I try to use an external script (https://libs.crefopay.de/3.0/secure-fields.js) which is not vue based
I added the script via -tags into index.html
But when I try to intsanciate an object, like in the excample of the script publisher.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
Vue says "'SecureFieldsClient' is not defined"
If I use this.
let secureFieldsClientInstance =
new this.SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
Vue says: Error in v-on handler: "TypeError: this.SecureFieldsClient is not a constructor"
My Code:
methods: {
startPayment () {
this.state = null
if (!this.selected) {
this.state = false
this.msg = 'Bitte Zahlungsweise auswählen.'
} else {
localStorage.payment = this.selected
let configuration = {
url: 'https://sandbox.crefopay.de/secureFields/',
placeholders: {
}
}
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
secureFieldsClientInstance.registerPayment()
// this.$router.replace({ name: 'payment' })
}
}
}
Where is my mistake?
EDIT:
Updated the hole question
Here is a minimal Vue app for the context your provided, which works:
https://codepen.io/krukid/pen/voxqPj
Without additional details it's hard to say what your specific problem is, but most probably the library gets loaded after your method executes, so window.SecureFieldsClient is expectedly not yet defined. Or, there is some runtime error that crashes your script and prevents your method from executing. There could be some other more exotic issues, but lacking a broader context I can only speculate.
To ensure your library loads before running any code from it, you should attach an onload listener to your external script:
mounted () {
let crefPayApi = document.createElement('script')
crefPayApi.onload = () => this.startPayment()
crefPayApi.setAttribute('src', 'https://libs.crefopay.de/3.0/secure-fields.js')
document.head.appendChild(crefPayApi)
},
I found the solution.
the import was never the problem.
I had just to ignore VUEs/eslints complaining about the missing "this" via // eslint-disable-next-line and it works.
So external fuctions/opbjects should be called without "this" it seems.
let secureFieldsClientInstance =
new SecureFieldsClient('xxxxx',
this.custNo,
this.paymentRegisteredCallback,
this.initializationCompleteCallback,
configuration)
You could download the script and then use the import directive to load the script via webpack. You probably have something like import Vue from 'vue'; in your project. This just imports vue from your node modules.
It's the exact same thing for other external scripts, just use a relative path. When using Vue-CLI, you can do import i18n from './i18n';, where the src folder would contain a i18n.js
If you really want to use a CDN, you can add it like you normally would and then add it to the externals: https://webpack.js.org/configuration/externals/#externals to make it accessible from within webpack