Skip to content

Scheduling problem when using Navigation.pushUrl #49

@Carlsson87

Description

@Carlsson87

I have discovered a problem that I suspect have to do with how commands and subscriptions are scheduled. I'll try to make clear what I have found so far. And since Ellie does not support Browser.application I'll paste an SSCCE here.

module Main exposing (main)

import Browser
import Browser.Events
import Browser.Navigation
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


type alias Model =
    { key : Browser.Navigation.Key
    , subscribeToAnimationFrames : Bool
    }


type Msg
    = Navigate
    | UrlChanged
    | AnimationFrame


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Navigate ->
            ( model
            , Browser.Navigation.pushUrl model.key "#foo"
            )

        UrlChanged ->
            ( { model | subscribeToAnimationFrames = True }
            , Cmd.none
            )

        AnimationFrame ->
            ( { model | subscribeToAnimationFrames = False }
            , Cmd.none
            )


view : Model -> Browser.Document Msg
view model =
    { title = "Test"
    , body =
        [ button [ onClick Navigate ] [ text "Click this button to cause the problem" ]
        , Html.h1 []
            [ Html.text "Subscribe to animation frames: "
            , Html.text (Debug.toString model.subscribeToAnimationFrames)
            ]
        , Html.pre
            []
            [ Html.text (Debug.toString model)
            ]
        ]
    }


subscriptions : Model -> Sub Msg
subscriptions model =
    if model.subscribeToAnimationFrames then
        Browser.Events.onAnimationFrame (always AnimationFrame)

    else
        Sub.none


main : Program () Model Msg
main =
    Browser.application
        { init = \_ _ key -> ( Model key False, Cmd.none )
        , onUrlChange = always UrlChanged
        , onUrlRequest = always Navigate
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

When the application receives the message Navigate it navigates to another url. When the browser changes url the message UrlChanged is sent to the application. When this happens the subscriptions that result from the first update gets applied after the subscriptions that result from the second update.

This means that when then UrlChanged message is sent to the application and I want to subscribe to Browser.Events.onAnimationFrame it is "cancelled" by the resulting subscriptions from the previous update. So even if model.subscribeToAnimationFrames is True there is no guarantee that the application is subscribed to Browser.Events.onAnimationFrame.

Let me know if I need to provide any more info.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions