Purescript Halogen: могу ли я запросить состояние дочернего компонента, который также является родительским?

Если у меня есть дедушка, дочерний компонент и компонент внука, может ли дедушка запросить состояние дочернего элемента? Я попытался использовать "запрос", как здесь, но типы не совпадают, когда вы запрашиваете состояние дочернего элемента, у которого также есть собственный дочерний элемент. Пример в руководстве работает нормально, когда я запрашиваю состояние ребенка, у которого нет детей.

Ошибка:

Could not match type

  Query

with type

  Coproduct (Coproduct Query (ChildF AnswerSlot Query)) Query

1 ответ

Решение

Определенно да. Вы, вероятно, просто скучаете по left в запросе к ребенку - это необходимо, поскольку алгебра запроса ребенка будет иметь вид Coproduct f (ChildF p f') с этим имея своего ребенка.

Соответственно, вы также можете запросить внука у деда, используя right и построение ChildF с соответствующими значениями для внука.

Я собрал надуманный пример опроса и ребенка, и внука, который, надеюсь, прояснит ситуацию:

module Main where

import Prelude

import Data.Functor.Coproduct (Coproduct, left, right)
import Data.Maybe (Maybe(..), fromMaybe)

import Debug.Trace (traceA) -- from purescript-debug

import Halogen as H
import Halogen.HTML as HH

--------------------------------------------------------------------------------

type GrandState = Unit
data GrandQuery a = AskGrandChild (String -> a)

grandchild :: forall g. H.Component GrandState GrandQuery g
grandchild = H.component { render, eval }
  where
  render :: GrandState -> H.ComponentHTML GrandQuery
  render _ = HH.div_ []
  eval :: GrandQuery ~> H.ComponentDSL GrandState GrandQuery g
  eval (AskGrandChild k) = pure $ k "Hello from grandchild"

--------------------------------------------------------------------------------

type ChildState = Unit
data ChildQuery a = AskChild (String -> a)
type GrandSlot = Unit

type ChildState' g = H.ParentState ChildState GrandState ChildQuery GrandQuery g GrandSlot
type ChildQuery' = Coproduct ChildQuery (H.ChildF GrandSlot GrandQuery)

child :: forall g. Functor g => H.Component (ChildState' g) ChildQuery' g
child = H.parentComponent { render, eval, peek: Nothing }
  where
  render :: ChildState -> H.ParentHTML GrandState ChildQuery GrandQuery g GrandSlot
  render _ = HH.slot unit \_ -> { component: grandchild, initialState: unit }
  eval :: ChildQuery ~> H.ParentDSL ChildState GrandState ChildQuery GrandQuery g GrandSlot
  eval (AskChild k) = pure $ k "Hello from child"

--------------------------------------------------------------------------------

type ParentState = Unit
data ParentQuery a = Something a
type ChildSlot = Unit

type ParentState' g = H.ParentState ParentState (ChildState' g) ParentQuery ChildQuery' g ChildSlot
type ParentQuery' = Coproduct ParentQuery (H.ChildF ChildSlot ChildQuery')

parent :: forall g. Functor g => H.Component (ParentState' g) ParentQuery' g
parent = H.parentComponent { render, eval, peek: Nothing }
  where
  render :: ParentState -> H.ParentHTML (ChildState' g) ParentQuery ChildQuery' g ChildSlot
  render _ = HH.slot unit \_ -> { component: child, initialState: H.parentState unit }
  eval :: ParentQuery ~> H.ParentDSL ParentState (ChildState' g) ParentQuery ChildQuery' g ChildSlot
  eval (Something next) = do

    -- note the `left` here
    childAnswer <- H.query unit $ left $ H.request AskChild
    traceA $ fromMaybe "child not found" $ childAnswer

    grandAnswer <- H.query unit $ right $ H.ChildF unit $ H.request AskGrandChild
    traceA $ fromMaybe "grandchild not found" $ grandAnswer

    pure next
Другие вопросы по тегам