Search code examples
javascriptdelayelmlagsubscriptions

UI lag between my javascript and my ported elm


I have a navbar which needs to change colour on scroll. This functionality was originally built with js, however now it has a 'Login' button which is built in elm to perform other functionality.

I used a port and subscription to change the colour of the elm login button using the original js. The colour change works however sometimes there is a lag between the login button and the rest of the navbar changing colour and so the button momentarily disappears. Sometimes however the colour change is seamless.

I tried switching the order in which the js function and the subscription was sent to see if it would make a difference, but it didn't. I understand the fact that elm is asynchronous will impact the order in which it/the js displays but I'm not sure how I can make it smooth in this situation.

Does anyone know how I can remove this lag?

Here is the js ports code:

window.onscroll = function() {
  if (this.scrollY <= 20) {
    if (!isTop) {
      isTop = true;
      setTransparentNav(); // this is a simple CSS class change fn
      app.ports.colorChanges.send(isTop); // this is the UI which is lagging
    }
  } else {
    if (isTop) {
      isTop = false;
      setBlackNav();
      app.ports.colorChanges.send(isTop);
    }
  }
};

This is the port in the Elm:

port colorChanges : (Bool -> msg) -> Sub msg

The message it sends is a simple Bool which when True dictates which classes are used.


Solution

  • Wherever possible I find it best to maintain a clear boundary line between Elm and vanilla UI. That way it's much harder to encounter problems with the Elm renderer acting in a different way to vanilla js.

    So in your instance I wouldn't use a nav made up of a mix of basic html/js elements and Elm elements. Instead I would either:

    • Use standard html and js to create the login button, with ports attached to click handlers to open any Elm login modals (or ports from Elm to JS for button text changes, etc.).

    Or

    • Rebuild the rest of the nav in Elm so all rendering is handled in the same way.