<p dir="auto">Here's my problem.</p>
<p dir="auto">Using react-router 1.0, i'm going to be re-rendering trees that are 90% the same. We use an external lib for an api that produces video mark up. Totally out of our hands. They modify the dom and that's how it has to be.</p>
<p dir="auto">My problem comes in that when the routing changes, it re-renders the tree, and wipes out the custom DOM put in by the third party api.</p>
<p dir="auto">I've tried things like returning false from <code class="notranslate">shouldComponentUpdate</code> always.. using <code class="notranslate">dangerouslySetInnerHtml={{__html: ''}}</code> to a blank string hoping that react would internally not do diff's on it.. nothing seems to work.</p>
<p dir="auto">Is there anything I can do to stop it?</p>
<p dir="auto">When writing a component that contains a set of large subtrees that stay relatively the same, but are simply moved around such that React's virtual DOM diffing can't detect the movement, React will end up recreating huge trees it should simply be moving.</p>
<p dir="auto">For example, pretend <code class="notranslate">blockA</code> and <code class="notranslate">blockB</code> are very large structures. They may be made of several levels of children and components. For example one could be the entire page contents and the other the sidebar, while this <code class="notranslate">render()</code> is the page root.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="render() {
    var blockA = &lt;div&gt;AAA&lt;/div&gt;,
        blockB = &lt;div&gt;BBB&lt;/div&gt;;

    if ( this.props.layoutA ) {
        return &lt;div&gt;
            &lt;div className=&quot;something&quot;&gt;{blockB}&lt;/div&gt;
            &lt;div className=&quot;something&quot;&gt;{blockA}&lt;/div&gt;
        &lt;/div&gt;;
    } else {
        return &lt;div&gt;
            {blockA}
            {blockB}
        &lt;/div&gt;;
    }
}"><pre class="notranslate"><span class="pl-en">render</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">blockA</span> <span class="pl-c1">=</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>AAA<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">,</span>
        <span class="pl-s1">blockB</span> <span class="pl-c1">=</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>BBB<span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>

    <span class="pl-k">if</span> <span class="pl-kos">(</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">props</span><span class="pl-kos">.</span><span class="pl-c1">layoutA</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
            <span class="pl-c1">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">className</span><span class="pl-c1">=</span><span class="pl-s">"something"</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">blockB</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
            <span class="pl-c1">&lt;</span><span class="pl-ent">div</span> <span class="pl-c1">className</span><span class="pl-c1">=</span><span class="pl-s">"something"</span><span class="pl-c1">&gt;</span><span class="pl-kos">{</span><span class="pl-s1">blockA</span><span class="pl-kos">}</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
        <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-c1">&lt;</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span>
            <span class="pl-kos">{</span><span class="pl-s1">blockA</span><span class="pl-kos">}</span>
            <span class="pl-kos">{</span><span class="pl-s1">blockB</span><span class="pl-kos">}</span>
        <span class="pl-c1">&lt;</span><span class="pl-c1">/</span><span class="pl-ent">div</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Because the blocks aren't at the same level React cannot see the relation between these blocks and <code class="notranslate">key</code> cannot be used to give React any hints. As a result, when <code class="notranslate">layoutA</code> is changed, instead of the two blocks being moved to their new location the entire page is essentially completely unrendered and then re-rendered from scratch.</p>
<p dir="auto">I understand why this is the case. It would be far to expensive for React to be able to detect movement of nodes like this.</p>
<p dir="auto">But I do believe we need a pattern to hint to React that this component has large blocks that may be moved around at different levels.</p>
<p dir="auto">Note that there may be a component in between the rendering component root and the block. So parent semantics scoped to the nearest component won't work. This'll need owner scoping.</p>
<p dir="auto">I understand that React is trying to eliminate the need for React.createElement to be used and owner scoping within special attributes interferes with that. So instead of a component scoped <code class="notranslate">key=""</code> variant I think a method/object style interface kind of like <code class="notranslate">React.addons.createFragment</code> might work.</p>