question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow to skip sub tree patching.

See original GitHub issue

I’m trying to use preact as rendering tool for web components custom elements. I saw the proposal solution on https://github.com/bspaulding/preact-custom-element

But in my case it is not works properly. First is that I do not using shadow-dom (shadowDOM is imperative and do not allow prerender custom-elements on server side, what I want to achieve). Second is that I’m trying to mix preact app and preact base custom-elements, or same effect will be when I will nest the preact base custom-elements within preact base custom-elements.

I prepared example https://www.webpackbin.com/bins/-Ki44_xg5yie0o-jHaXv

Problem is that there is no any isolation between the parent render scope (eg root vnodes tree) and nested render scope (eg. some subbranch of vnode tree).

Custom elements should care about render cycle by itself, diff algorithm should never tray to patch the content of custom-elements (even the custom-element will not use the preact). The proposal https://github.com/bspaulding/preact-custom-element toVdom is not solving the problem and is very inefficient.

I tried locally simple patch:

https://github.com/developit/preact/blob/master/src/vdom/diff.js#L128 replaced by:

var isCE = !!window.customElements.get(vnode.nodeName);

if (!isCE) {
    // Optimization: fast-path for elements containing a single TextNode:
    if (!hydrating && vchildren && vchildren.length===1 && typeof vchildren[0]==='string' &&
        fc!=null && fc.splitText!==undefined && fc.nextSibling==null) {
        if (fc.nodeValue!=vchildren[0]) {
            fc.nodeValue = vchildren[0];
        }
    }
    // otherwise, if there are existing or new children, diff them:
    else if (vchildren && vchildren.length || fc!=null) {
        innerDiffNode(out, vchildren, context, mountAll, hydrating ||
            props.dangerouslySetInnerHTML!=null);
    }
} 

And after such change everything is works fine. I know this is not something what preact team will accept 😃 But maybe you can add some handler to the options like:

options.skip: (vnode, dom) 

and use it:

var skip= options.skip && options.skip(vnode, dom);

if (!skip) {
    // Optimization: fast-path for elements containing a single TextNode:
    if (!hydrating && vchildren && vchildren.length===1 && typeof vchildren[0]==='string' &&
        fc!=null && fc.splitText!==undefined && fc.nextSibling==null) {
        if (fc.nodeValue!=vchildren[0]) {
            fc.nodeValue = vchildren[0];
        }
    }
    // otherwise, if there are existing or new children, diff them:
    else if (vchildren && vchildren.length || fc!=null) {
        innerDiffNode(out, vchildren, context, mountAll, hydrating ||
            props.dangerouslySetInnerHTML!=null);
    }
} 

and usage for custom elements:

preact.options.skip = (vnode) => typeof vnode == 'string' && !!window.customElements.get(vnode.nodeName);

Such skip option can be used also as a solution for ‘render once’ when we know that some sub tree do not have to be never rerendered:

    // preact-one
   function once(vnode) {
        vnode.renderOnce = true;
        return vnode
   }
  
   preact.options.skip = (vnode, dom) => vnode.renderOnce && dom

and usage

    renderApp() {
         render(
           <div> 
                once(<div>Static header which will be never rerendered</div>)
                <div>Content rerendered always<div> 
           </div>, document.body);
    }

The other possibility is to add the property to vnode and instead of condition on options.skip check the property.

if (!vnode.skipChildren) {
    // Optimization: fast-path for elements containing a single TextNode:
    if (!hydrating && vchildren && vchildren.length===1 && typeof vchildren[0]==='string' &&
        fc!=null && fc.splitText!==undefined && fc.nextSibling==null) {
        if (fc.nodeValue!=vchildren[0]) {
            fc.nodeValue = vchildren[0];
        }
    }
    // otherwise, if there are existing or new children, diff them:
    else if (vchildren && vchildren.length || fc!=null) {
        innerDiffNode(out, vchildren, context, mountAll, hydrating ||
            props.dangerouslySetInnerHTML!=null);
    }
} 

Then options.vnode can be use to decorate vnode with such options.

As a last word, I can say that many virtual dom implementations provides possibility to ‘skip’ the subtree patching: https://github.com/google/incremental-dom/blob/master/test/functional/skip.js https://github.com/Matt-Esch/virtual-dom/blob/master/docs/thunk.md

Best Regards

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:12 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
treshugartcommented, Jul 7, 2017

Wow, so skate going in same direction, but probably because they are always using shadow dom they do not see this problem.

Just for posterity, we allow this now via a custom renderRoot property.

1reaction
majo44commented, Apr 21, 2017

Wow, so skate going in same direction, but probably because they are always using shadow dom they do not see this problem. (I will try to convince them to add possibility to render also without shadow dom 😃 This will give a possibility to render skate.js components on server side by domino)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Subtree patching · Issue #45 - GitHub
I would like to use subtree patching. Subtree patching would cut the need to recurse through all tree nodes, constructing all vnodes and...
Read more >
Use Device Tree Overlays to Patch Your Device Tree
Device tree overlays are special device tree blob fragments that allow you to override specific parts of a device tree on-the-fly, before booting...
Read more >
git - When applying a patch is there any way to resolve conflicts?
When rebasing I just right click the folder and use tortioseGit and select the resolve option. This brings up a nice gui to...
Read more >
Add the option in system menu block to "Expand all items in ...
Problem/Motivation. Right now using the core menu block subtrees aren't show unless they are in the active trail.
Read more >
Steam Workshop::[DEPRECATED] Tree & Vehicle Props Patch
The game doesn't allow props to have submesh. ... This patch mod will automatically skip those vehicles and trees to avoid the errors....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found