Skip to content

Clean old events handler when HMR is trigger #14

@MangelMaxime

Description

@MangelMaxime

Description

When working on Thoth.Elmish.Toast I discovered that previous event handler are not cleaned HMR update. This is normal, because HMR can't know how to clean the old events handlers.

I managed to write a fix for this

// If HMR support is active, then we provide have a custom implementation.
// This is needed to avoid:
// - flickering (trigger several react renderer process)
// - attaching several event listener to the same event
if not (isNull HMR.``module``.hot) then
    if HMR.``module``.hot.status() <> HMR.Idle then
        Browser.window.removeEventListener(eventIdentifier, !!Browser.window?(eventIdentifier))

    Browser.window?(eventIdentifier) <- fun (ev : Browser.Event) ->
        let ev = ev :?> Browser.CustomEvent
        dispatch (Add (unbox ev.detail))

    Browser.window.addEventListener(eventIdentifier, !!Browser.window?(eventIdentifier))
else
    Browser.window.addEventListener(eventIdentifier, !^(fun ev ->
        let ev = ev :?> Browser.CustomEvent
        dispatch (Add (unbox ev.detail))
))

This is a known problem when using HMR, we need to clean the "global states" (event listener, global variables, etc) by ourself even in pure JavaScript.

At the time I was thinking that the Program.toNavigable was ok in current state because it's checking capturing when the newLocation is equal to lastLocation.

But it's not enough in fact, because when we have an HMR update I think we are creating a new Elmish instance. And so each instance is having its own handlers and lastLocation reference.

So for example, if in your code base when you have a page change you send a request to the server then you will send X request to your server. In the same way, I do have some concurrent race and each application try to render it's own view when a page change and it's causing some visual flickering.

In general, the renderered view is the newest program registered so this is why no one noticed this problem yet.

I will send a PR to remove old events listeners when using Program.toNavigable


On a side note, I will try to see if we can also completly kill the previous Elmish instance as they are still in running in memories.

Here I triggered 3 updates of the code and so have:

  • Fleet Mapping aka instance n°1
  • Instance n°2
  • Instance n°3
  • Instance n°4

capture d ecran 2018-11-06 a 11 58 43

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions