在 Elm 中使用 Dict.update 和嵌套更新函数
Using Dict.update with nested update functions in Elm
我正在编写一个 Elm 应用程序,其中状态的主要部分处于 Dict
状态,Record
s 作为值。我有一个主状态模型的更新函数,以及 Dict
中各个记录的更新函数。有没有办法使用 Dict.update
和记录状态更新功能?
我遇到的问题是记录的状态更新函数 returns 通常更新函数 return:一个包含更新对象和任何触发命令的元组(例如 (newRecord, Cmd.none)
).但是 Dict.update
函数需要接收一条记录和 return 一条记录(例如 newRecord
),而不是带有记录和命令对象的元组。
有办法解决这个问题吗?现在我已经使用 Dict.get
和 Dict.insert
的组合让它工作,但这看起来很笨拙。
据我所知没有。我的一个项目中有这个辅助函数
updateDict : comparable -> msg -> Dict comparable b -> (msg -> b -> ( b, Cmd msg )) -> (comparable -> msg -> c) -> ( Dict comparable b, Cmd c )
updateDict uid act dict fn wrapper =
case Dict.get uid dict |> Maybe.map (fn act) of
Just ( m, e ) ->
( Dict.insert uid m dict
, Cmd.map (wrapper uid) e
)
Nothing ->
( dict, Cmd.none )
不确定这是否是您要查找的内容,但如果您的模型中有嵌套 Dict
结构,如下所示:
type alias Model =
{ parentsAndChildren : Dict String (Dict String Int) }
那就没必要让childupdate
输出一个Cmd
。您的更新可能如下所示:
update : Msg -> Model -> Model
update msg model =
case msg of
NewChild parentName childName age ->
let
newModel =
{ model
| parentsAndChildren =
model.parentsAndChildren
|> Dict.update
parentName
(Maybe.map insertChild)
}
in
(newModel, Cmd.none)
-- helper function to update a child Dict
insertChild: String -> Int -> Dict (String Int) -> Dict (String Int)
insertChild name age childDict =
Dict.insert name age childDict
NEEDS 输出 Cmd
的唯一 update
函数是顶级组件中的更新函数。
所以你的 child update
函数不必输出 Cmd
.
如果记录的更新函数总是return Cmd.none
,你可以简化它并且return只更新模型。
如果您的应用程序体系结构不需要,则子模块不必遵循 ( Model, Cmd Msg )
约定。
如果您确实需要从较低级别传递命令,也可以重新构建子模块的 update
函数以简化这些更新。
示例基于 example/http
这是一个示例,说明如何拆分更新,以便您可以在顶级 update
中重复使用相同的逻辑,而无需额外的技巧。
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(updateModel msg model, updateCmd msg model)
updateCmd: Msg -> Model -> Cmd Msg
updateCmd msg model =
case msg of
MorePlease ->
getRandomGif model.topic
_ ->
Cmd.none
updateModel: Msg -> Model -> Model
updateModel msg model =
case msg of
NewGif (Ok newUrl) ->
Model model.topic newUrl
_ ->
model
如果您需要 updateCmd
中的更新模型,则只需传递它而不是当前模型,或者如果您愿意,甚至可以传递两者。
作为奖励,您可以完全省略 case 表达式中未使用的分支。
使用Dict.update
也可以在 Dict.update
中使用 updateModel
而无需检索记录并将其写回。
Dict.update childKey (Maybe.map (updateModel childMsg)) model
我正在编写一个 Elm 应用程序,其中状态的主要部分处于 Dict
状态,Record
s 作为值。我有一个主状态模型的更新函数,以及 Dict
中各个记录的更新函数。有没有办法使用 Dict.update
和记录状态更新功能?
我遇到的问题是记录的状态更新函数 returns 通常更新函数 return:一个包含更新对象和任何触发命令的元组(例如 (newRecord, Cmd.none)
).但是 Dict.update
函数需要接收一条记录和 return 一条记录(例如 newRecord
),而不是带有记录和命令对象的元组。
有办法解决这个问题吗?现在我已经使用 Dict.get
和 Dict.insert
的组合让它工作,但这看起来很笨拙。
据我所知没有。我的一个项目中有这个辅助函数
updateDict : comparable -> msg -> Dict comparable b -> (msg -> b -> ( b, Cmd msg )) -> (comparable -> msg -> c) -> ( Dict comparable b, Cmd c )
updateDict uid act dict fn wrapper =
case Dict.get uid dict |> Maybe.map (fn act) of
Just ( m, e ) ->
( Dict.insert uid m dict
, Cmd.map (wrapper uid) e
)
Nothing ->
( dict, Cmd.none )
不确定这是否是您要查找的内容,但如果您的模型中有嵌套 Dict
结构,如下所示:
type alias Model =
{ parentsAndChildren : Dict String (Dict String Int) }
那就没必要让childupdate
输出一个Cmd
。您的更新可能如下所示:
update : Msg -> Model -> Model
update msg model =
case msg of
NewChild parentName childName age ->
let
newModel =
{ model
| parentsAndChildren =
model.parentsAndChildren
|> Dict.update
parentName
(Maybe.map insertChild)
}
in
(newModel, Cmd.none)
-- helper function to update a child Dict
insertChild: String -> Int -> Dict (String Int) -> Dict (String Int)
insertChild name age childDict =
Dict.insert name age childDict
NEEDS 输出 Cmd
的唯一 update
函数是顶级组件中的更新函数。
所以你的 child update
函数不必输出 Cmd
.
如果记录的更新函数总是return Cmd.none
,你可以简化它并且return只更新模型。
如果您的应用程序体系结构不需要,则子模块不必遵循 ( Model, Cmd Msg )
约定。
如果您确实需要从较低级别传递命令,也可以重新构建子模块的 update
函数以简化这些更新。
示例基于 example/http
这是一个示例,说明如何拆分更新,以便您可以在顶级 update
中重复使用相同的逻辑,而无需额外的技巧。
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
(updateModel msg model, updateCmd msg model)
updateCmd: Msg -> Model -> Cmd Msg
updateCmd msg model =
case msg of
MorePlease ->
getRandomGif model.topic
_ ->
Cmd.none
updateModel: Msg -> Model -> Model
updateModel msg model =
case msg of
NewGif (Ok newUrl) ->
Model model.topic newUrl
_ ->
model
如果您需要 updateCmd
中的更新模型,则只需传递它而不是当前模型,或者如果您愿意,甚至可以传递两者。
作为奖励,您可以完全省略 case 表达式中未使用的分支。
使用Dict.update
也可以在 Dict.update
中使用 updateModel
而无需检索记录并将其写回。
Dict.update childKey (Maybe.map (updateModel childMsg)) model