title: It's it possible to get React to move an element rather than re-create it when it changes its place in the DOM?
body: <p>It's it possible to get React to move an element rather than re-create it when it changes its place in the DOM?</p>
  
  <p>Let's imagine I'm making a 2 pane component and I want to be able to hide/unhide one pane. Let's also imagine the panes themselves are very heavy. In my case the each pane has over 2000 elements.</p>
  
  <p>In my actual code I'm using a splitter when there are 2 panes. In order to show just one pane I need to remove the splitter and replace it with a div.</p>
  
  <p>The code below simulates this. If there's one pane it uses a <code>div</code> to contain the pane. If there's 2 panes it uses <code>pre</code> to contain them. In my case it would be <code>div</code> with 1 pain and a <code>splitter</code> with 2.</p>
  
  <p>So, instrumenting <code>document.createElement</code> I see that not only are the containers created but the elements inside are recreated. In other words, in my code when go from splitter->div the 2000+ element pane will get entirely recreated which is slow.</p>
  
  <p>Is there a way to tell React effectively. "Hey, don't recreate this component, just move it?"</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>class TwoPanes extends React.Component {
    constructor(props) {
      super(props);
    }
    render() {
      const panes = this.renderPanes();
      if (panes.length === 2) {
        return React.createElement('pre', {className: "panes"}, panes);
      } else {
        return React.createElement('div', {className: "panes"}, panes);
      }
    }
    renderPanes() {
      return this.props.panes.map(pane =&gt; {
        return React.createElement('div', {className: "pane"}, pane);
      });
    }
  }
  
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        panes: [
          "pane one",
          "pane two",
        ],
      };
    }
    render() {
      const panes = React.createElement(TwoPanes, {panes: this.state.panes}, null);
      const button = React.createElement('button', {
        onClick: () =&gt; {
          const panes = this.state.panes.slice();
          if (panes.length === 1) {
            panes.splice(0, 0, "pane one");  // insert pane 1
          } else {
            panes.splice(0, 1);  // remove pane 1
          }
          this.setState({panes: panes});
        },
      }, "toggle pane one");
      return React.createElement('div', {className: "outer"}, [panes, button]);
    }
  }
  
  // wrap document.createElement so we can see if new elements are created
  // vs reused
  document.createElement = (function(oldFn) {
    let count = 0;
    let inside = false;
    return function(type, ...args) {
      if (!inside) {  // needed because SO's console wrapper calls createElement
        inside = true;  
        console.log(++count, "created:", type);
        inside = false;
      }
      return oldFn.call(this, type, ...args);
    }
  }(document.createElement));
    
    
  ReactDOM.render(
    React.createElement(App, {}, null),
    document.getElementById('root')        
  );</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>html { box-sizing: border-box; }
  *, *:before, *:after { box-sizing: inherit; }
  body { margin: 0; }
  #root { width: 100vw; height: 100vh; }
  .outer { 
    width: 100%; 
    height: 100%; 
  }
  .panes { 
    width: 100%; 
    height: 100%; 
    display: flex;
    flow-direction: row;
    justify-content: space-between;
  }
  .pane {
    flex: 1 1 auto;
    border: 1px solid black;
  }
  button {
    position: absolute;
    left: 10px;
    top: 30px;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"&gt;&lt;/script&gt;
  &lt;div id="root"&gt;&lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>