Как я могу эффективно перейти на значение внутри Reflex.Dynamic?

Допустим, у меня есть некоторое состояние приложения, поддерживаемое в некоторой бэкэнд-системе. Это выглядит так

data MyState = State1 MyState1 | State2 MyState2

data MyState1 = MyState1 { ms1_text :: Text, ms1_int :: Int }
data MyState2 = MyState2 { ms2_bool :: Bool, ms2_maybe_char :: Maybe Char }

У меня также есть функция, чтобы получить последнее состояние от бэкэнд-системы

getLatestState :: IO MyState

Я почти уверен, что смогу выяснить, как упаковать это в Dynamic, многократно запрашивая серверную часть, так что у меня есть

dynMyState :: MonadWidget t m => Dynamic t MyState

Я хочу сделать это в HTML. Я хочу, чтобы каждая часть структуры данных отображалась в div. Тем не менее, вещи, которые не существуют, не должны отображаться вообще, поэтому, когда ms2_maybe_char является Nothingне должно быть никакого div для этого, и когда MyState это State1не должно быть никакого div для State2,

пара примеров для наглядности:

State1 (MyState1 "foo" 3)

становится

<div class=MyState1>
    <div>foo</div>
    <div>3</div>
</div>

а также

State2 (MyState2 False Nothing)

становится

<div class=MyState2>
    <div>False</div>
</div>

В идеале, каждая часть DOM должна быть изменена только при необходимости - так что если ms2_maybe_char изменения от Nothing в Just 'a'Затем необходимо создать новый div. Или если ms1_text изменения от "foo" в "bar"тогда нам нужно изменить эту строку в DOM. Тем не менее, изменение ms1_text никогда не должен вызывать перерисовку родственных или родительских узлов.

Как мне структурировать мой код? Возможно ли это, учитывая getLatestState API как строительный блок? Я полностью упускаю смысл Рефлекса, пытаясь построить из одного Dynamic значение, и мне нужно переосмыслить свой подход?

В частности, самый первый камень преткновения заключается в том, что я не могу легко проверить Dynamic, чтобы узнать, содержит ли он State1 или State2. Я мог бы потенциально использовать dyn или же widgetHold здесь и fmap функция над dynMyState который может рассматривать состояние как простое значение и генерировать m () действие, которое привлекает все это. Но затем я теряю все возможности совместного использования - весь интерфейс пользователя будет перерисовываться с нуля при каждом изменении состояния.

Примечание: это более подробный вопрос для продолжения, как я могу перейти на значение внутри Reflex Dynamic?, Что отличается / яснее в этом вопросе, так это дополнительное желание не терять эффективные обновления всего, что находится в проверяемом значении. Спасибо всем, кто помог в этом вопросе!

1 ответ

Ответ зависит от того, каковы ваши цели и требования. Если вы хотите наилучшего возможного совместного использования dom, полученного из двух отдельных функций renderState1 а также renderState2Я думаю, что требует virtual-dom,

Но на самом деле это звучит так, будто вы хотите иметь точный контроль над тем, что будет добавлено в DOM, когда.

Что-то простое вы можете сделать, если у вас есть измененные версии renderState1 а также renderState2 в руке, что каждый взять Maybe State1 или же Maybe State2 Аргумент состоит в том, чтобы создать пару этих динамических майбов и использовать атрибуты css, чтобы скрыть один или другой:

let mState1 = (\c -> case c of
                  s@(State1 _ _) -> Just s
                  _              -> Nothing
              ) <$> dynMyState
    mState2 = (\c -> case c of
                  s@(State2 _ _ _) -> Just s
                  _                -> Nothing
    nothingHider a m =
       let atr = bool mempty ("style" =: "displayNone") . isJust <$> a
       in  elDynAttr "div" atr (m a)

nothingHider mState1 renderMaybeState1
nothingHider mState2 renderMaybeState2

Если вы получите Призмы, то от этой неловкости можно избавиться.

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