Matt-Esch / virtual-dom

A Virtual DOM and diffing algorithm
MIT License
11.65k stars 780 forks source link

Problem with [Function] patch, updates DOM incorrectly. #418

Closed sadiqevani closed 7 years ago

sadiqevani commented 7 years ago

Hello,

So, i am trying to programaticaly generate a Virtual DOM through some other libraries, and render everytime i push some specific changes to the BODY.

But currently i am having issues with duplicated content and the ability of virtual-dom/patch to create the correct DOM representation.

Example:

<div>
hey
<h1>hey</h1>
</div>

I make the change to the following markup:

<div>
hey
<h3>hey</h3>
</div>

This is the result:

screenshot 2016-12-02 17 05 13

I get duplicated content, even i change the entire DOM to something different, the update does not happens.

It ads the content to the DOM but does not update/remove.

Everything is based off the Body tag, so its a single ROOT being rendered.

screenshot 2016-12-02 17 07 20 screenshot 2016-12-02 17 07 51

Help would be really appreciated, or if someone has faced a similar issue!

dashkb commented 7 years ago

I'm having a similar issue, but I'm not able to reproduce it with a trivial example (so I suspect it may be in my code someplace.)

The interesting bit is that I've just come back from a two-week vacation, and I'm sure it was working before I left. (I know, I know...) Maybe a dependency broke? :cringe:

Some screenshots that may help:

pre-update, paused in patchRecursive for the patch that fails -- you can see here that the patch has the correct target node, but index[nodeIndex] returns the wrong target.

post-update -- this is the failed update, which given the previous screenshot is what we'd expect. The 'footer' is replaced with the new content.

I'm trying to figure it out... I don't see too much activity on this repo so not sure if we'll get any help. I'll update here if I make any progress.

dashkb commented 7 years ago

OK, figured out my issue, and it was my fault. I was trying to be clever and automatically insert style nodes into my components, but in some cases the nodes had no content. I tried to reproduce it with an empty div but that doesn't cause a problem; must be something about an empty style tag that throws off the indices in the patching process.

Check to make sure you aren't adding any garbage to the DOM that might be confusing the patching machinery. I'd still call this a bug, but at least I can work around it.


Edit: OK, that wasn't even it.

I'm adding my style nodes to a VirtualNode instance, which isn't kosher because VirtualNode's constructor does some counting which must be used to generate indices for patching. So, after reading that function, it looked like I had to increase the count of the destination node by the count of the node I'm inserting, plus one for the node itself, which makes sense. Something like:

tree.children.unshift(node)
tree.count = tree.count + node.count + 1

This may or may not be similar to your issue.

sadiqevani commented 7 years ago

@dashkb

In my case i had a different issue. The problem for me was that i was doing Tree dehydration and then pushing it into the server and then sending it back through sockets and then hydrating it. But in that case when i was doing Diff -> Patch, i had to give as an Argument the previous Tree to compare then, the Patch would generate the correct output.

At the same time, i also included the "key" property in the VNodes, so that might have fixed it as well, but for now its working fine.

jorgebucaran commented 7 years ago

Hey @sadiqevani! I tried following the steps from the issue above, but I couldn't replicate the issue. Can you share the problematic code?

EDIT: I just noticed you reported the issue as solved since it was a problem in your logic.

@dashkb Did you figure out the issue in your case?

sadiqevani commented 7 years ago

Hey @jbucaran

I figured it out! The problem as mentioned above, was simply i had to compare the previous state, of the AST Tree with the new one and then apply the patches.

But i decided to go with VueJS and its Parser/Compiler for the thing i am working. They have done almost everything i was trying to do with the Virtual-Dom 😃