Bad title because I haven't quite pinned down exactly the core features of this bug. However, I do have a MWE.
Our setup is morally
type Model = Array Box
type Box = { id :: Int, text :: String }
data Msg = Msg Int String
Our initial model is of two boxes with distinct IDs and texts. Our update function accepts a Msg id text and updates the box with the given id to have the given text; additionally, it also swaps the order of the two boxes.
When an update is invoked by a button onClick, handler, the state updates and is re-rendered as expected.
However, when an updated is invoked by textarea onInput handler, though the state updates properly (I have verified this with Debug.log), the re-render is wrong: the content of both boxes is changed, not just one. Additionally, after the re-render, the wrong textarea is focused. See the gif below.
Full MWE is given below:
module Main where
import Prelude
import Effect (Effect)
import Effect.Uncurried (runEffectFn1)
import Partial.Unsafe (unsafePartial)
import Platform as Platform
import Html (Html)
import Html as H
import Css as S
import Attribute as A
type Id = Int
type Model = Array Box
data Msg = Msg_SwapBoxesAndSetText Id String
type Box = { id :: Id , text :: String }
initialModel :: Model
initialModel =
[ { id: 1, text: "text A" }
, { id: 2, text: "text B" }
]
main :: Effect Unit
main = do
let app = Platform.app
{ init: \_ -> pure initialModel
, subscriptions: \_ -> mempty
, update: \model msg -> pure (update model msg)
, view: view
}
(runEffectFn1 app) unit
update :: Model -> Msg -> Model
update boxes (Msg_SwapBoxesAndSetText targetBoxId newText) =
boxes # map updateBox # swapOrder
where
updateBox box = if box.id == targetBoxId then box { text = newText } else box
swapOrder = unsafePartial $ \[a, b] -> [b, a]
view :: Model -> { head :: Array (Html Msg), body :: Array (Html Msg) }
view boxes =
{ head: []
, body:
[ H.button [ A.onClick $ Msg_SwapBoxesAndSetText 1 "new text" ] [ H.text "swap boxes and set box #1 text to 'new text'" ] ]
<>
( boxes # map \box ->
H.divS
[ S.backgroundColor $ if box.id == 1 then "rgba(200 0 0 / 20%)" else "rgba(0 200 0 / 20%)" ]
[ ]
[ H.p
[ ]
[ H.text $ "Box #" <> show box.id ]
, H.textarea
[ A.onInput \text -> Msg_SwapBoxesAndSetText box.id text ]
[ H.text $ box.text ]
]
)
}
Bad title because I haven't quite pinned down exactly the core features of this bug. However, I do have a MWE.
Our setup is morally
Our initial model is of two boxes with distinct IDs and texts. Our update function accepts a
Msg id text
and updates the box with the givenid
to have the giventext
; additionally, it also swaps the order of the two boxes.When an update is invoked by a button
onClick
, handler, the state updates and is re-rendered as expected.However, when an updated is invoked by textarea
onInput
handler, though the state updates properly (I have verified this withDebug.log
), the re-render is wrong: the content of both boxes is changed, not just one. Additionally, after the re-render, the wrong textarea is focused. See the gif below.Full MWE is given below: