How to Use Your Own Commands in Bucklescript-TEA

Sometimes, you need to do something tricky after you update your model/state. Or it doesn’t necessarily have to be tricky, but it just has to happen after you modify the state and the rest of your app updates.

Like, what happens if you want to scroll to a certain position on a page, but after the model has updated and page has been refreshed with new data?

So what do you do then?

You can send your own Commands (Cmd ) at the end of your update function!

What, we’ll do then is create a Msg (in this case I’m using the scrolling example):

type Msg
  = ...
  | ...
  | Scroll

Then we need to encapsulate the Msg in a command. To do that, we’ll use Tasks.

If you’re having trouble using Tasks, you take a look here at my other article on a potential fix: How to include Tasks in Bucklescript-TEA

Here’s the type signature for Task.perform:

perform : (a -> msg) -> Task Never a -> Cmd msg

You can see that it returns a Cmd msg, that’s just what we need.

Usually, you use tasks for http requests or doing something outside of Bucklescript-TEA runtime, like trying to get the time, but in this case, we are using it send our own Msgs.

At first, the type sig is a bit confusing, at least from the Elm docs. But basically, what we it saying is this:

perform : (fun a -> returns msg) -> Task that never fails a -> Cmd msg

So, how do we get a Task that never fails, we can use Task.succeed:

succeed : a -> Task x a
	succeed 42    -- results in 42

So, since in this case, I don’t really need to pass any extra info with my Msg, I can just subsitute using a () and get this:

Task.perform (fun _ -> Scroll) (Task.succeed ())

and then in your update function, just use it in the place of a Cmd:

let update model msg =
  match msg with
  | SomethingHappened ->
    let page_position = calculate_new_page_position in
    { model with page_postion 
    }, Task.perform (fun _ -> Scroll) (Task.succeed ())
  | Scroll ->
    scollToPagePosition model.page_position
    { model }, Cmd.none

I’m not sure this is the best solution for scrolling after an update, but it works. Scrolling is not critical, and doesn’t necessarily have to immediate, so this solution is adequate.