Extracted from https://github.com/facebook/react/issues/12643.

We're currently diff a host node in the complete phase even if it has bailed out in the begin phase. By itself, this just means we're doing a little bit more work than necessary. But it also has some observable effects. In particular, https://github.com/facebook/react/issues/13424 (which by itself would be very rare and probably not worth fixing) is made worse because we end up committing update to inputs from another component.

I have a fix for this in https://github.com/facebook/react/pull/13423. Filing this for posterity.
render() {
        return [<NullComponent key="a" />, <div key="b" />, <span key="c" />];
      }
    }
    let instance = null;
    ReactDOM.render(<Fragment ref={ref => (instance = ref)} />, container);
    expect(container.childNodes.length).toBe(2);
    const firstNode = ReactDOM.findDOMNode(instance);
    expect(firstNode).toBe(container.firstChild);
    expect(firstNode.tagName).toBe('DIV');
  });
  it('renders an empty fragment', () => {
    const Div = () => <div />;
    const EmptyFragment = () => <React.Fragment />;
    const NonEmptyFragment = () => (
      <React.Fragment>
        <Div />
      </React.Fragment>
    );
    ReactDOM.render(<EmptyFragment />, container);
    expect(container.firstChild).toBe(null);
    ReactDOM.render(<NonEmptyFragment />, container);
    expect(container.firstChild.tagName).toBe('DIV');
    ReactDOM.render(<EmptyFragment />, container);
    expect(container.firstChild).toBe(null);
    ReactDOM.render(<Div />, container);