# Understanding the "double update" behavior of Browser.application

**URL:** <https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963>\
**Category:** Learn\
**Created:** [January 16, 2019, 5:25pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963 "2019-01-16T17:25:56Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![lenards](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lenards/32/820_2.png) [@lenards](https://discourse.elm-lang.org/u/lenards)\
**Post date:** [January 16, 2019, 5:25pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/1 "2019-01-16T17:25:56Z")

</div>

Hi all,

I’m working upgrading to Elm 0.19. Our main was using `Navigation.programWithFlags` and I’ve shifted to Browser.application. In my efforts to understand what was needed, I was reviewing experience reports like [@jerith 's update experience report.](https://discourse.elm-lang.org/t/a-0-19-update-experience-report/2593).

I wanted to understand a line in here:

> elm-route-url does seem to still be necessary: Browser.application still has a “double-update problem”.

I have realized that I don’t fully understand the impact of switching directly to `Browser.application`. I’m running into some problems, and I thought I would step back to learn/understand more.

So what behavior is being referred to here? Is the `update` function passed to `Browser.application` being called twice with the same `msg`?

I imagine this is a wider context for the behavior. I hope to grok this, and appreciate any thoughts. I reached out to @jerith about this on Elm Slack, and he thought others may be interested in this (and would like to contribute to this topic, as well).

Thank you.

---

<div class="post-metadata">

**Author:** ![Sebastian](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sebastian/32/98_2.png) [@Sebastian](https://discourse.elm-lang.org/u/Sebastian)\
**Post date:** [January 17, 2019, 1:01am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/2 "2019-01-17T01:01:45Z")

</div>

Any more background on this double-updated problem? That linked report doesn’t have any more context.

---

<div class="post-metadata">

**Author:** ![lenards](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lenards/32/820_2.png) [@lenards](https://discourse.elm-lang.org/u/lenards)\
**Post date:** [January 17, 2019, 2:20am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/3 "2019-01-17T02:20:36Z")

</div>

Yes, the experience report didn’t have that detail. I was reaching out to @jerith over Elm Slack to get some more details. He asked if I might start a topic here so that others might contribute.

It’s a great suggestion too, since if _lots_ of people asked him - it might get tiring to repeat yourself.

With the topic creating, it’s a placeholder for a potential response.

---

<div class="post-metadata">

**Author:** ![jerith](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jerith/32/114_2.png) [@jerith](https://discourse.elm-lang.org/u/jerith)\
**Post date:** [January 17, 2019, 4:08am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/4 "2019-01-17T04:08:48Z")

</div>

The easiest way to understand the problem, I think, is by starting with the example program in the [guide’s section on `Browser.application`](https://guide.elm-lang.org/webapps/navigation.html). In that example, the control flow for clicking on a link looks like this:

```
<a href="/path"/>
    \
     \- click on it -->-- Elm runtime >-\
                                         onUrlRequest function
                                           |
                                           v
                                         LinkClicked message
                                           |
                                           v
                                         pushUrl cmd
                      /-< Elm runtime <-/
  onUrlChange function
    |
    v
  UrlChanged message
    |
    v
  update function enacts model update for "/path" URL

```

There is a double-update in a sense here, because as you can see we have two messages (`LinkClicked` and `UrlChanged`) flowing through two invocations of our `update` function. However, they’re well-ordered and serve two different purposes, pretty clearly explained in the guide.

In 0.18 and earlier, things were not nearly this nice. The [documentation for `elm-route-url`](https://package.elm-lang.org/packages/rgrempel/elm-route-url/4.0.0) explains this pretty well, but in short you had a lot of bookkeeping to do on your own. I sank quite a lot of time into trying to make that work before discovering `elm-route-url`, and it was a pain.

In the above diagram, it’s important to note that, if you want any _data_ to ride along with the user’s click on that `/path` link, you must **encode** that data in the URL itself. And then you have **parse it back out** when it comes into (the second invocation of) your `update` function.

That parsing work does have to be done if you want to support “deep linking” into your SPA. And the encoding work does also have to be done if you want to generate those deep links. But it feels like a big sacrifice to give up the strongly-typed messages that you see in most Elm architecture examples. :-/

So, given all of that, my app in 0.18 and before works off of `div`s that produce messages `onClick`. However, doing it that way, as in [this modification to the guide’s example code](https://github.com/jerith666/elbum/commit/6da530843348368081d4dcfba159a32ae5007565#diff-2bfd5c5bdbff5686d2fbd979ad451206), yields this control flow:

```
<div onClick="Goto"/>
    \
     \- click on it -->-- Elm runtime >-\
                                         Goto message
                                           |
                                           v
                                         pushUrl cmd
                /----< Elm runtime <----/ |
  onUrlChange fn |
    | |
    v v
  UrlChanged message --> update fn enacts model update for Goto message

```

This is the double update problem: there are two arrows going into the `update` function that both want to enact the model update. If you run [the code](https://raw.githubusercontent.com/jerith666/elbum/6da530843348368081d4dcfba159a32ae5007565/src/client/AppExample.elm), you’ll see that clicking on the `<a/>`s increments the counter by one, but clicking the `<div/>` increments it by two. (You can’t just ignore the `UrlChanged` message because that’s the **only** one that happens on back/forward navigation.)

So, if you take the approach of driving your app with `div onClick` rather than `a href`, then `elm-route-url` is still necessary in order to take care of the bookkeeping and prevent the double updates. Unfortunately we’re [still working on updating it for 0.19](https://github.com/rgrempel/elm-route-url/issues/37) – help is appreciated! 🙂

(This example program just needs some [very trivial bookkeeping](https://github.com/jerith666/elbum/commit/ed9539a7766012d7067f24cab7850b5485714feb#diff-2bfd5c5bdbff5686d2fbd979ad451206) to make it work, but in general it’s more complex.)

I think it would be a nice addition if `pushUrl` took a `type ChangeNotification = InvokeUrlChange | SkipUrlChange` argument; that would really alleviate the problem.

---

<div class="post-metadata">

**Author:** ![lenards](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lenards/32/820_2.png) [@lenards](https://discourse.elm-lang.org/u/lenards)\
**Post date:** [January 17, 2019, 2:56pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/6 "2019-01-17T14:56:51Z")

</div>

Thanks Matt. I phrased the topic as the “double update” behavior because I really didn’t have the before to see if it was a problem. I’m mulling what you’ve provided and I am quite grateful for this detail and thoughtfulness.

---

<div class="post-metadata">

**Author:** ![jerith](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jerith/32/114_2.png) [@jerith](https://discourse.elm-lang.org/u/jerith)\
**Post date:** [January 17, 2019, 5:25pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/7 "2019-01-17T17:25:54Z")

</div>

I should add that in general I think it’s preferable to use `a href`s, you get a lot of things for free with them (hover states, open-in-new-tab, etc. etc.) that you have to build yourself or live without if you use `div onClick`s. So maybe what I really want is a way for an `a href` to say “i don’t need to handle this twice in `update`, give me the short-circuit pure-elm strongly-typed alternative”. (There’s a lot of hand-waving there, hopefully you understand my high-level point though.)

---

<div class="post-metadata">

**Author:** ![lenards](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lenards/32/820_2.png) [@lenards](https://discourse.elm-lang.org/u/lenards)\
**Post date:** [January 17, 2019, 5:31pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/8 "2019-01-17T17:31:12Z")

</div>

I think I understand it at a high level. In the upgrade effort I’m working on, I was confused about how to handle `a href` and was going down the `onClick` path.

The application I’m work on also has a complexity that I don’t want to bother too many with … but the Elm app is hosted _within_ another application (an [ASP.NET](http://ASP.NET) MVC app) so you’re point about "`External` might not have a different domain" lands for me.

In essence, I moved the app from `Navigation.programWithFlags` to `Browser.application` without **a proper, strong understanding** of that impact. Thank you for politely pointing back to the docs for Browser.application.

---

<div class="post-metadata">

**Author:** ![jerith](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jerith/32/114_2.png) [@jerith](https://discourse.elm-lang.org/u/jerith)\
**Post date:** [January 17, 2019, 5:48pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/9 "2019-01-17T17:48:15Z")

</div>

Hm … if you’re dealing with an app that doesn’t control the whole page, you should also consider the issues discussed at [the docs for `Browser.Navigation.Key`](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Navigation#Key) and the “annoying bugs” link therein. You probably don’t want to / can’t use `Browser.application` in your case for those reasons anyway! 🙂

---

<div class="post-metadata">

**Author:** ![lenards](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/lenards/32/820_2.png) [@lenards](https://discourse.elm-lang.org/u/lenards)\
**Post date:** [January 17, 2019, 5:50pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/10 "2019-01-17T17:50:04Z")

</div>

The application controls the “whole” page for a sub-select of possible _pages_.

I have been considering that I need to shift to `Browser.element`, even if that entire pageview is rendering by Elm.

And, apologies for diverting attention from the central topic.

---

<div class="post-metadata">

**Author:** ![Sebastian](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sebastian/32/98_2.png) [@Sebastian](https://discourse.elm-lang.org/u/Sebastian)\
**Post date:** [January 17, 2019, 10:06pm UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/11 "2019-01-17T22:06:45Z")

</div>

So as I understand you want to pass additional data when navigating, without having to serialise and deserialise from the URL. What copying links and the back button. I think that having to serialise in the URL is a good thing when working with the web platform.

Also:

```auto
Goto url ->
            ( { model | url = url, n = model.n + 1 }, Nav.pushUrl model.key <| Url.toString url)

```

In here I don’t think you should set things in the model, it should probably be:

```auto
Goto url ->
            ( model, Nav.pushUrl model.key <| Url.toString url)

```

But I don’t see how setting the url twice could be a problem.

---

<div class="post-metadata">

**Author:** ![jerith](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jerith/32/114_2.png) [@jerith](https://discourse.elm-lang.org/u/jerith)\
**Post date:** [January 26, 2019, 1:36am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/12 "2019-01-26T01:36:26Z")

</div>

Setting the URL twice is a problem because you end up with duplicate history entries. So the user has to push back twice when they expect to only have to push it once.

---

<div class="post-metadata">

**Author:** ![Sebastian](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/sebastian/32/98_2.png) [@Sebastian](https://discourse.elm-lang.org/u/Sebastian)\
**Post date:** [January 27, 2019, 4:56am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/13 "2019-01-27T04:56:01Z")

</div>

Sorry, I meant setting the URL twice in the model as shown in [https://raw.githubusercontent.com/jerith666/elbum/6da530843348368081d4dcfba159a32ae5007565/src/client/AppExample.elm](https://raw.githubusercontent.com/jerith666/elbum/6da530843348368081d4dcfba159a32ae5007565/src/client/AppExample.elm). This doesn’t create duplicate history.

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [February 6, 2019, 5:02am UTC](https://discourse.elm-lang.org/t/understanding-the-double-update-behavior-of-browser-application/2963/14 "2019-02-06T05:02:40Z")

</div>

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