Skip to content
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

Rendering a component must reconcile against previous DOM state #124

Merged
merged 1 commit into from
Jul 1, 2017

Conversation

pdf
Copy link
Contributor

@pdf pdf commented Jun 30, 2017

The renderComponent function incorrectly presumed that prevRender from the component context must be the previous DOM state, however elements may have been shuffled/removed between component renders for persistent component pointers.

Fixes #123

@codecov-io
Copy link

codecov-io commented Jun 30, 2017

Codecov Report

Merging #124 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #124   +/-   ##
=======================================
  Coverage   64.72%   64.72%           
=======================================
  Files           5        5           
  Lines         309      309           
=======================================
  Hits          200      200           
  Misses         97       97           
  Partials       12       12
Impacted Files Coverage Δ
dom.go 70.77% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1d751e8...20be68a. Read the comment docs.

domutil.go Outdated
panic("vecty: Missing parent node")
}

return parent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove blank line 11 here

domutil.go Outdated
parent := node.Get("parentNode")
if parent == nil {
panic("vecty: Missing parent node")
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this function at all (instead of just invoking node.Get("parentNode) directly and assuming the result is non-nil. It'll panic just the same, and I hope that real user applications won't ever hit either of these cases.

Copy link
Contributor Author

@pdf pdf Jul 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly because a panic on null is not very informative. If you'd prefer not to take this change, I'm okay with that since it's not functionally important, but the explicit panic makes it very obvious what happened when this behaviour is triggered.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I'd prefer to drop this part of the change if you're alright with that. I think that a package should really only panic (esp. with a vecty: prefix) if the user of the library did something obviously wrong. In this case.. I don't think this will be triggered due to a user error, so I'd prefer to keep the (less informative) nil pointer panic here.

@slimsag
Copy link
Member

slimsag commented Jul 1, 2017

I don't fully understand this change, so I'd like to ask a few questions.

  1. Why is it that Rerender cannot utilize comp.Context().prevRender?
  2. If it's true that Rerender can't utilize comp.Context().prevRender, then what about other users of that variable? Can those also be incorrect, or no (why)?

I see the example code in #123 (comment) but as far as I can tell from this PR, Rerender passes c and c.Context().prevRender as arguments to renderComponent, which then seems to directly use that c.Context().prevRender argument for reconciliation. So I don't see why renderComponent needs this new argument or how it fixes the issue.

On tests: I'm fine to merge this without tests once I understand it, but let's add a TODO in the test file that links to this PR for adding tests later.

@pdf
Copy link
Contributor Author

pdf commented Jul 1, 2017

In the case of Rerender with a top-level component, that works fine. What we're looking at here though is a component (pointer) that's rendered as a child of the Rerender target (somewhere down the render tree). If the component is a pointer that persists between renders, Context().prevRender for that component is not nil, but bears no relationship to what's actually in the DOM at that point (in the example, the child component's nodes have been removed from the DOM entirely, and the new render should cause it to replace some other elements, instead reconcile tries to manipulate nodes that don't exist).

The child component must be reconciled against the sibling DOM that the parent rendered in the previous pass.

On tests: I'd definitely appreciate a hand working out how to sensibly test nested elements/components (in #29)

@pdf pdf force-pushed the gh_123 branch 2 times, most recently from f1a3a78 to ad9067e Compare July 1, 2017 07:56
@slimsag
Copy link
Member

slimsag commented Jul 1, 2017

Ok, that makes a lot more sense. Would I be correct in assuming that this also helps #78 then (although notably still retaining this panic)?

On tests: I'd definitely appreciate a hand working out how to sensibly test nested elements/components (in #29)

I'll see if I can find some time soon to look into this.

@slimsag
Copy link
Member

slimsag commented Jul 1, 2017

Once #124 (comment) is addressed I will merge. For now, though, it's quite late here so I must catch some sleep. :)

The `renderComponent` function incorrectly presumed that `prevRender`
from the component context must be the previous DOM state, however
elements may have been shuffled/removed between component renders for
persistent component pointers.

Fixes hexops#123
@pdf
Copy link
Contributor Author

pdf commented Jul 1, 2017

I think #78 should be close to solved with this merge, combined with the rework of render/renderComponent/reconcile, but I've not tested sufficiently to call it conclusively.

@slimsag
Copy link
Member

slimsag commented Jul 1, 2017

Fair enough. I'll post my thoughts on that issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants