-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memoized elements are removed & added anyway #77
Comments
Currently struggling with this too. This demo I made might help visualize the problem: http://requirebin.com/?gist=0f7bb3b03959448e120f02d506f4cd7e |
The element you're holding a reference to gets moved to the new tree when you pass the template to Because the reference is an element, it's unique and can't live in two places at once. In your breakpoint, you should see the element disappear. When that happens, you get the |
Thanks. So can this be fixed/worked around? Or is storing an element in a variable a no-go for effective morphdom diff? |
If you don't try to memoize the element, just make |
I was trying to solve this issue choojs/nanohtml#26 by storing an image in a var as @yoshuawuyts suggested, so that a network request wouldn’t be made each time render is called:
And storing an element is useful sometimes, like for SVG icons in a separate file, which I now have to turn into functions, which is probably fine. This also seems to be related to an issue I was having when elements would not only re-render all the time, but not show up at all: choojs/nanohtml#27. |
I think this is what you're trying to do: http://requirebin.com/?gist=07d10f19b4d8b3c229eab907a50df3b9 I'm using |
Thanks! That makes sense, yes. A bit cumbersome to use manually though. Maybe there should be some higher-lever abstraction that is aware of |
Hi @AutoSponge, thanks for the feedback. The use case that prompted the report originally was rendering a Leaflet map using an application framework that re-renders the page using morphdom any time a piece of state changes. Other libraries like d3 may do this as well, where calling their Here's how I've implemented a map for my use case - it currently re-initializes if there's a state change though. |
I think there are two issues here, and I want to make sure I address both. First, my response before dealt with using a reference which causes a "flash" as an element leaves the However, this does not help the second issue which is that For your map example, I altered your component slightly and it seems to work (but you know the code better): module.exports = (coords) => {
if (coords) {
// If new coords or el hasn't been created already, create one
// otherwise, cached el will be returned
if (!isEqual(coords, cache.coords) || !cache.el) {
cache.coords = coords
if (cache.map) cache.map.remove()
cache.el = html`<div class="map" id="map" onload=${onload} onunload=${onunload}></div>`
return html`<div>${cache.el}</div>`
}
return html`<div>${cache.el.cloneNode(true)}</div>`
} else {
return html`<div class="map"></div>`
} The idea is that returning a clone of your cached element will copy all of the changes made by leafelet and cause no updates to the original element which would break the map. If this works for you, that's great, but it won't change my approach to the |
I see the benefit of having a memoized HTML element, but the problem is that when Here's the relevant code in morphdom: Lines 513 to 516 in 3101545
Thoughts? If that sounds good, would anyone be interested in submitting a PR? EDIT: I think the key thing here is that the memoized DOM node can never be put in the real DOM because |
Just like I put the The |
Btw, the cached node must be put into the DOM the first time because the 3rd-party side effects need to be cloned. But this may be the point to experiment with Vdom because the element could live in a Vdom tree. |
I believe an improvement to |
I see your point about efficiency. If we choose to use a vdom object or custom element that The question then is, how to make this work with actual DOM? I'm going to test this out, but what if we used a custom element that implemented |
@AutoSponge diffing a virtual DOM node with a real DOM node definitely has promise. There would need to be the ability to upgrade the virtual DOM node to a real DOM node and that could also be done using the |
@patrick-steele-idem I'll try to make a POC for this using a custom component since that implementation is somewhat clear to me. |
@patrick-steele-idem I made this (quick and dirty) example: https://github.com/AutoSponge/morphdom-cached-node/blob/master/app.js so you can see what I mean. I put the |
Hello, I'd like to cross-post the issue shama/on-load#10 as @shama and @yoshuawuyts have suggested the issue may reside in morphdom.
I reported that:
@shama investigated, reproduced the issue, and diagnosed that:
The following code sample illustrates the issue, with a live demo here:
Expected behaviour:
child on
only gets called once, when the element is mounted.Actual behaviour:
child on
andchild off
are also called at re-render, even though the child element was already memoized.This issue prevents things like memoizing leaflet/d3 components so they don't have to be re-initialized at every state change. Any suggestions on how we might resolve this?
The text was updated successfully, but these errors were encountered: