Update UI with `setViewportOf` and `view` as atomic operation

To avoid UI flickering in my application, I’d like to execute the effects of setViewportOf and view in the same frame. I have two questions on this topic:

  1. Does Elm make any guarantees such that I can write code in a way that ensures that the effects of setViewportOf and view occur in the same frame? I was able to achieve this but I want to make sure this is part of a contract and I’m not relying on implementation details that may change.
  2. Assuming we have a solution to (1), consider this more complicated scenario. Suppose you want to use the information from getViewportOf to calculate the scroll position to pass to setViewportOf. My instinct was to chain them together with Task.andThen but this caused the effects of setViewportOf and view to occur in different frames. What’s the idiomatic way to chain together getViewportOf and setViewportOf such that the effects of setViewportOf and view occur in the same frame?

Minimal Examples

I made a couple of relevant examples in Ellie:

  1. setViewportOf with Flickering. This example chains together getViewportOfand setViewportOf and this results in the UI flickering. Read the comments at the top of the Elm source file to understand how to use the example.
  2. setViewportOf without Flickering. This example removes the call to getViewportOf. The effects of setViewportOf and view appear to be executed in the same frame but I’m not sure whether this is by contract or due to relying on implementation details that may change.

Real World Example

You can see a real world example of this challenge in elm-selectize. If you try out the demo and hold the down arrow to move through the menu options, you’ll notice that the background of the selected item appears to flicker (only happens when the scrollview scrolls to reveal the newly selected item). Looking at the source, you can see it chains together getViewportOf and setViewportOf just as I described above.

4 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.