Способ диспетчеризации для родительской дочерней композиции
Я пытаюсь понять, как басня должна работать с родительской дочерней композицией. Все довольно просто, когда дело доходит до update
метод, init
и определение команд. Но view
метод и его dispatch
метод сложно выяснить
В моем коде ребенок это:
module DeploymentView
type DeploymentTypeView =
| DeployContainerView
type Model = {
CurrentView : DeploymentTypeView option
}
type Msg =
| ShowDeployContainer
let init () : Model =
let initialModel = {
CurrentView = None
}
initialModel
let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
match msg with
| ShowDeployContainer ->
let nextModel = {
currentModel with CurrentView = Some DeployContainerView
}
nextModel, Cmd.none
| _ -> currentModel, Cmd.none
let view (model : Model) (dispatch : Msg -> unit) =
[
Content.content [ Content.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Left) ] ]
[
Heading.h3 [] [ str ("Deployments: ") ]
]
Columns.columns []
[
Column.column [] [ button "deploy container" (fun _ -> dispatch ShowDeployContainer) ]
]
]
И после этой документации об обработке родительского потомка я определил родителя как этот:
module Client
type PortalView =
| DeploymentView of DeploymentView.Model
| ProductAdministrationView
type Model = {
CurrentPortal : PortalView option
}
// The Msg type defines what events/actions can occur while the application is running
// the state of the application changes *only* in reaction to these events
type Msg =
| ShowDeployment
| ShowAdministration
| DeployContainerView of DeploymentView.Msg
// defines the initial state and initial command (= side-effect) of the application
let init () : Model * Cmd<Msg> =
let initialModel = {
CurrentPortal = None
}
initialModel, Cmd.none
let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
match msg with
| ShowDeployment ->
let nextModel = {
currentModel with CurrentPortal = Some <| DeploymentView(DeploymentView.init())
}
nextModel, Cmd.none
| ShowAdministration ->
let nextModel = {
currentModel with CurrentPortal = Some ProductAdministrationView
}
nextModel, Cmd.none
| DeployContainerView msg' ->
let res, cmd =
match currentModel.CurrentPortal with
| Some(DeploymentView(m)) -> DeploymentView.update msg' m
| _ -> DeploymentView.init(), Cmd.none
{ currentModel with CurrentPortal = Some(DeploymentView(res)) }, Cmd.map DeployContainerView cmd
Пока все хорошо, моя проблема возникает, когда речь идет о рендеринге самого представления. Клиентское представление использует функцию следующим образом:
let view (model : Model) (dispatch : Msg -> unit)
где Msg
имеет тип DeploymentView.Msg
тогда как в родительском представлении у меня есть доступ к отправке типа Client.Msg -> unit
, как я могу разложить родительскую диспетчеризацию, чтобы сопоставить ее с дочерней сигнатурой диспетчеризации?
1 ответ
Вы можете очень легко создать диспетчерскую функцию, которая соответствует ожиданиям ребенка, используя >>
оператор:
DeploymentView.view deploymentViewModel (DeployContainerView >> dispatch)
что эквивалентно выполнению:
DeploymentView.view deploymentViewModel (fun msg -> msg |> DeployContainerView |> dispatch)
То есть он оборачивает сообщение ребенка в DeployContainerView
, а затем передает это dispatch
,
С другой стороны, общепринятым и хорошим соглашением является использование Msg
суффикс конструкторов, используемых для переноса дочерних элементов msg
типы. Вы можете рассмотреть возможность переименования DeployContainerView
в DeploymentContainerMsg
,