假设我有一些应用程序状态,在某个后端系统上维护。看起来像这样
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
我很确定我可以通过反复查询后端来弄清楚如何将其打包成动态,这样我就有了
dynMyState :: MonadWidget t m => Dynamic t MyState
我想把它渲染成 html。我希望数据结构的每个部分都呈现给一个 div。但是,根本不应该渲染不存在的东西——所以,当ms2_maybe_char
is时Nothing
,它不应该有 div,而当MyState
is a时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
to更改Just 'a'
,则需要创建一个新的 div。或者如果ms1_text
从"foo"
变为"bar"
,那么我们需要在 DOM 中更改该字符串。但是,更改ms1_text
不应导致重绘兄弟节点或父节点。
我应该如何构建我的代码?getLatestState
考虑到api 作为构建块,这甚至可能吗?我是否完全错过了 Reflex 的要点,试图建立一个单一的Dynamic
价值,我需要重新考虑我的方法?
特别是,第一个绊脚石是我无法轻松检查 Dynamic 以了解它是否包含 State1 或 State2。我可以在这里使用dyn
or widgetHold
,以及fmap
一个dynMyState
可以将状态视为简单值并生成m ()
绘制整个事物的动作的函数。但是,然后我失去了所有的共享——整个 UI 将在每次状态更改时从头开始重新绘制。
注意:这是一个更详细的后续问题,我如何在 Reflex Dynamic 内的值上进行分支?. 这个问题的不同/更清楚的是,不丢失检查值内所有内容的有效更新的额外愿望。感谢所有在这个问题上提供帮助的人!