我试图在threepenny-gui设置一个IORef,但我无法让它工作。在我的应用程序中,IORef本身将更复杂,而不是自己显示 - 但这个例子证明了我认为的问题。
这是我的尝试:
testIORef2 :: IORef String -> Window -> UI ()
testIORef2 ref window = void $ do
return window # set title "Test IORef"
inCell <- UI.input
outCell <- UI.input
getBody window #+ [
column [
grid [[string " In cell::", element inCell]
,[string "Out cell::" , element outCell ]]
, string "Cells should update while typing."
]]
-- When value changes write to IORef
on UI.valueChange inCell $ \_ -> do
inValue <- get value inCell
liftIO $ writeIORef ref inValue
-- Read the IORef
refVal <- liftIO $ readIORef ref
-- Behaviour which holds the string value in the input cell
inValue <- stepper "0" $ UI.valueChange inCell
-- Behaviour which holds the value in the ref
let outValue = (const refVal) <$> inValue
-- Set the value of the output cell to the outValue
element outCell # sink value outValue
代码排序有效,但outValue不是最新的。
如何修复它以便及时更新。此外,欢迎对代码进行任何改进。
感谢。
答案 0 :(得分:2)
您编写的代码可能不是您打算做的。这条线
let outValue = (const refVal) <$> inValue
指定outValue
是Behavior
,其值恒定且等于refValue
。反过来,后一个值来自
refVal <- liftIO $ readIORef ref
表示IORef
monad中UI
此时存储的值。
使用IORef
时,您希望在更改内容时读取引用的值,并使用此值修改UI内容,例如:
on UI.valueChange inCell $ \_ -> do
inValue <- get value inCell
liftIO $ writeIORef ref inValue
outValue <- liftIO $ readIORef ref
element outCell # set value outValue
出于一致性(操作顺序)的原因,不建议使用IORef
作为Behavior
的来源 - 它是后者还是前者。
答案 1 :(得分:0)
我不是三便秘的专家,但这是我的猜测。
您在外部编写的代码on
事件处理程序只执行一次。因此,您希望在所述处理程序中包含outValue
update ,例如
-- When value changes write to IORef
on UI.valueChange inCell $ \_ -> do
inValue <- get value inCell
liftIO $ writeIORef ref inValue
... -- compute outValue
element outCell # sink value outValue