I’ve made a proof-of-concept project trying to replicate some of the react suspense features in this repository. This project is a recreation of this react suspense demo.

What’s good about suspense? Some features caught my attention:

# Data load co-located with the view

Usually in Elm the data fetching is at the router or some other place far from the view, having them together can make it easier to follow where the data is going and also move a view around in a more “plug-and-play” manner

For slow internet speeds we usually show a “Loading” message for the users, which is great and elm notably helps us a lot about not forgetting that. But, for fast internet connections, a “Loading” flicking really quick all the time can be very annoying.

We do not have to decide between one case or the other though, we can make the experience great for both at once, and suspend helps with that through the timeout component, which shows a “Loading” message, but only after some miliseconds.

On the web it’s common to render the html as soon as we get it, and different pieces like images load one after another, top to bottom, causing a lot of layout changes until everything’s in place.

But we can have a better experience than that, with suspense, we can wait util everything is fully ready before rendering the screen for the user

# Demos

## Slow internet connection without Suspense features

With a slow internet the “Loading…” is ok, but the images load little by little, causing a little bit of agony

## Fast internet connection with Suspense features

Everything looks instant now, no more screen flickings or layout change

# How it works

In order for all this to work, I had to subvert the elm-architecture a little bit to be able to return Cmds while rendering, which means that you can load data, but that’s nicely wrapper around the idea of caches to your date. If you have a view that needs to load some data, you can do it like this:

On the example above, the view won’t render until the data is ready, but sometimes you want to render at least something to give feedback to the user, you can do that using the timeout function, in which you can specify a fallback and a time for it to show. You can also replace this with the suspense function if you don’t want to have any fallbacks.

The interesting part is that this function can be many parents above with many levels of suspended or regular views inside it, it’s not directly bound to the data loading.

You can use the function preloadImg to render a view only after a image is loaded, it’s as simple as this:

## Other details

There are also other helper functions like mapCmdView and mapCmdViewList to help you wrapping the html inside the suspense features, and you also need to add some boilerplate on your main Msg, Model and Update for all this architectural change to work. Check the src/ folder for more examples.

# Conclusion

Having suspense features can really help achieving a great user experience. Implementing that in Elm was much harder than just using it in React, but it is definitively possible and the final API became kinda easy to use.

What do you think? Should I turn elm-suspense into a library? Suggestions are welcome!

More details in the repository:

https://github.com/rogeriochaves/elm-suspense