代码之家  ›  专栏  ›  技术社区  ›  Jason O.

在Elm中优雅地处理标志中丢失的键

  •  2
  • Jason O.  · 技术社区  · 7 年前

    我的应用程序通过标志从localstorage获取初始模型值。我向模型中添加了一个新键,它在启动Elm应用程序时会导致错误,因为通过标志传递的值中缺少键(“bar”)。考虑到将来可以添加更多的新键,并且我不想每次都必须清除localstorage,有没有办法告诉Elm在标志中缺少键时分配默认值?

    type alias Model =
        { foo : String, bar : Int }
    
    update : msg -> Model -> ( Model, Cmd msg )
    update _ model =
        model ! []
    
    view : Model -> Html msg
    view model =
        text <| toString model
    
    main : Program Flags Model msg
    main =
        Html.programWithFlags
            { init = init
            , update = update
            , view = view
            , subscriptions = always Sub.none
            }
    

    <body>
      <script>
        var app = Elm.Main.fullscreen({foo: "abc"})
      </script>
    </body>
    
    1 回复  |  直到 7 年前
        1
  •  7
  •   Jason O.    7 年前

    Elm Slack channel的@ilias提供了一个很好的解决方案。

    https://ellie-app.com/mWrNyQWYBa1/0

    module Main exposing (main)
    
    import Html exposing (Html, text)
    import Json.Decode as Decode exposing (Decoder)
    import Json.Decode.Extra as Decode  --"elm-community/json-extra"
    
    
    type alias Model =
        { foo : String, bar : Int }
    
    
    flagsDecoder : Decoder Model
    flagsDecoder =
        Decode.map2 Model
            (Decode.field "foo" Decode.string |> Decode.withDefault "hello")
            (Decode.field "bar" Decode.int |> Decode.withDefault 12)
    
    
    init : Decode.Value -> ( Model, Cmd msg )
    init flags =
        case Decode.decodeValue flagsDecoder flags of
            Err _ ->
                Debug.crash "gracefully handle complete failure"
    
            Ok model ->
                ( model, Cmd.none )
    
    
    update : msg -> Model -> ( Model, Cmd msg )
    update _ model =
        model ! []
    
    
    view : Model -> Html msg
    view model =
        text <| toString model
    
    
    main : Program Decode.Value Model msg
    main =
        Html.programWithFlags
            { init = init
            , update = update
            , view = view
            , subscriptions = always Sub.none
            }
    

    HTML

    <body>
      <script>
        var app = Elm.Main.fullscreen({foo: "abc"})
      </script>
    </body>