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

(async-loader): Use reference in vnode for current node #1308

Closed
wants to merge 1 commit into from

Conversation

reznord
Copy link
Member

@reznord reznord commented Jul 8, 2020

Use the vnode to get access the DOM node (for getting the current element).

@developit 's magic 😄

Fixes #1293

@reznord reznord requested review from prateekbh and developit July 8, 2020 20:42
@developit
Copy link
Member

note: I haven't tested this yet, not actually sure if it works. It's also scary.

@reznord
Copy link
Member Author

reznord commented Jul 8, 2020

I did test this out on all the possible demos 😁

Copy link
Member

@prateekbh prateekbh left a comment

Choose a reason for hiding this comment

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

I can see the flash again because of this PR. I'll find a way to add a test around this tonight

developit added a commit that referenced this pull request Jul 9, 2020
I finally (FINALLY) found a solution for #1293, #1308, etc etc. This doesn't use DOM hacks or anything - it just crawls up the tree of VNodes and performs a Depth-First-Search backwards from the position of AsyncComponent in order to find the most recently hydrated DOM element. Essentially, the first populated `vnode._dom` reference it finds is guaranteed to be the previous sibling of the parent element AsyncComponent is about to get rendered into. As long as AsyncComponent isn't being used load a component that renders a Fragment, the nextSibling of that discovered element is the exact node Preact will try to hydrate.

In the case of an AsyncComponent wrapping a Fragment, only the first Fragment child will be hydrated. This means the remaining children will have the flicker effect, but that's pretty reasonable:

```js
// app.js
import Foo from 'async!./foo';
export default () => <div><Foo /></div>

// foo.js
export default () => <Fragment>
    <h1>Hello</h1>
    <p>world!</p>  // will be culled+reinserted during hydration
</Fragment>
```
@reznord
Copy link
Member Author

reznord commented Jul 9, 2020

Closing this in favour of #1309

@reznord reznord closed this Jul 9, 2020
reznord added a commit that referenced this pull request Jul 9, 2020
* Fix async-loader for Preact X

I finally (FINALLY) found a solution for #1293, #1308, etc etc. This doesn't use DOM hacks or anything - it just crawls up the tree of VNodes and performs a Depth-First-Search backwards from the position of AsyncComponent in order to find the most recently hydrated DOM element. Essentially, the first populated `vnode._dom` reference it finds is guaranteed to be the previous sibling of the parent element AsyncComponent is about to get rendered into. As long as AsyncComponent isn't being used load a component that renders a Fragment, the nextSibling of that discovered element is the exact node Preact will try to hydrate.

In the case of an AsyncComponent wrapping a Fragment, only the first Fragment child will be hydrated. This means the remaining children will have the flicker effect, but that's pretty reasonable:

```js
// app.js
import Foo from 'async!./foo';
export default () => <div><Foo /></div>

// foo.js
export default () => <Fragment>
    <h1>Hello</h1>
    <p>world!</p>  // will be culled+reinserted during hydration
</Fragment>
```

* Stop searching if we hit an element parent

Co-authored-by: Anup <allamsetty.anup@gmail.com>
@ForsakenHarmony ForsakenHarmony deleted the async-loader-current-node branch September 2, 2020 00:11
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.

Cannot import async components: Undefined component passed to createElement()
3 participants