AntoineW/luge

React : Element is not defined while compiling

Closed this issue · 14 comments

Hello,

The new version is working fine in developpment mode with React & Gatsby.
However when I try to build with the command gatsby build, I get this error :

WebpackError: ReferenceError: Element is not defined

  • luge.esm.js:1
    [gatsby-starter-hello-world]/[@Waaark]/luge/dist/js/luge.esm.js:1:1727

  • luge.esm.js:1
    [gatsby-starter-hello-world]/[@Waaark]/luge/dist/js/luge.esm.js:1:1659

  • luge.esm.js:1
    [gatsby-starter-hello-world]/[@Waaark]/luge/dist/js/luge.esm.js:1:1635

It seems that its because Element is a DOM API, however NodeJS environment doesn't have it.
I searched and found this topic : https://stackoverflow.com/questions/39357535/referenceerror-element-is-not-defined-when-running-mocha-tests-on-reactonsen
Seems like this package may solve the problem : https://github.com/rstacruz/jsdom-global

Best regards, and thanks for your help
By the way the plugin is working like a charm

Hi,
It seems more like a Gatsby related issue. I found this topic that talk about it gatsbyjs/gatsby#309 (comment)

I agree with the person who says that Gatsby should be responsible of making sure that browser-only packages like luge can work with their tool.

Did you try some of the workarounds explained here? https://www.gatsbyjs.com/docs/using-client-side-only-packages/#workaround-3-load-client-side-dependent-components-with-loadable-components

Or did you try to include jsdom inside your code? (note that the jsdom-global package you linked to seems outdated)

Hello,
Thanks for your answer.
I tried importing luge in the useEffect() hook, however is doesn't work on all the components of my apps doing this. (Whereas all is working fine importing it like a module in development mode)
I will try using React.Lazy, I keep you updated

Best regards

Using React.Lazy I have the same issue unfortunately. Not all the components are moving properly

In my previous answer I was linking to the #3 workaround, "Workaround 3: Load client-side dependent components with loadable-components" > https://www.gatsbyjs.com/docs/using-client-side-only-packages/#workaround-3-load-client-side-dependent-components-with-loadable-components

Did you try this?

@AntoineW Same issue using loadable components. I'm using dynamic rendering with loadable, not all the components are animated as they should

@chotardlucien I just tried to import luge through a component using useEffect and I can make it work in both develop and build mode.

I created a luge.js component like this:

import { useEffect } from "react"

const LugeReact = () => {
  useEffect(() => {
    import("@waaark/luge/dist/js/luge")
      .then((luge) => {
        luge.lifecycle.refresh()
      })
      .catch((error) => console.error(error));
  })

  return (null);
}

export default LugeReact

And then use it in my pages and it seems to work fine.
Did you manage to get through the build error? What kind of issue do you have now?

@chotardlucien I just tried to import luge through a component using useEffect and I can make it work in both develop and build mode.

I created a luge.js component like this:

import { useEffect } from "react"

const LugeReact = () => {
  useEffect(() => {
    import("@waaark/luge/dist/js/luge")
      .then((luge) => {
        luge.lifecycle.refresh()
      })
      .catch((error) => console.error(error));
  })

  return (null);
}

export default LugeReact

And then use it in my pages and it seems to work fine. Did you manage to get through the build error? What kind of issue do you have now?

@AntoineW
I couldn't access the lifecycle.refresh method when doing like this.
Now I found a way to do it :

import "@waaark/luge/dist/css/luge.css";
import luge from '@waaark/luge'

export default function luge({children,location}) {
    luge.lifecycle.add('reveal', (done) => {
        setTimeout(()=>{
            luge.lifecycle.refresh()
        },1500)
      }, 100, 'load')

    useEffect(()=>{
        setTimeout(()=>{
            luge.lifecycle.refresh()
        },1500)
    },[location])

    return (
        <div  data-lg-smooth className="scroll-container">
            {children}
        </div>
    )
}

Maybe there is a better way to make Luge refresh when changing page, but I didn't found how to do it using the lifecycle.add method.
Also i'm using setTimeout because I'm dynamically rendering the components from the Strapi API. It's kind of dirty but also I didn't found a better way to do it when all the components are rendered and all the images loaded.

Last issue : when adding lot of parallax and reveal in one page, some of them are not triggered. Idk why

@chotardlucien is your code available online somewhere on a repo? I'd like to dig a bit deeper to see what's going on.

@AntoineW I invited you on the repo

@chotardlucien thanks!

Unfortunately for now dynamic components are a specific case that doesn't have a clean solution in luge. Initially luge wasn't created with JS frameworks in mind so DOM Nodes added after the page load are not taken into account. The luge.lifecycle.refresh() method allows to refresh the entire page but calling it on each dynamic components many times per page, or using a timeout like you did is not super clean.

I will work on a new version that works better with dynamic components, but for now I don't have a clean solution to your issue.

@chotardlucien thanks!

Unfortunately for now dynamic components are a specific case that doesn't have a clean solution in luge. Initially luge wasn't created with JS frameworks in mind so DOM Nodes added after the page load are not taken into account. The luge.lifecycle.refresh() method allows to refresh the entire page but calling it on each dynamic components many times per page, or using a timeout like you did is not super clean.

I will work on a new version that works better with dynamic components, but for now I don't have a clean solution to your issue.

@AntoineW I would be the first to use it! The library is really nice and can't find an other one with good performance and no virtual scroll (chrome last update killed it)

Thanks for your help, can't wait the new version :)

Related to this discussion I worked on a small improvement that adds a new luge.emitter.emit('update') event to that allows to initialize the newly added elements after page load. That could be a better solution than calling luge.lifecycle.refresh() for dynamic components.

Related to this discussion I worked on a small improvement that adds a new luge.emitter.emit('update') event to that allows to initialize the newly added elements after page load. That could be a better solution than calling luge.lifecycle.refresh() for dynamic components.

@AntoineW I will give it a try this week-end and keep you updated

@chotardlucien did you get a chance to try?