GridView does apply its own implicit emptyText value during its rendering. The code has

Code:
    afterRender : function() {
        if (!this.ds || !this.cm) {
            return;
        }
        
        this.mainBody.dom.innerHTML = this.renderBody() || ' ';
        this.processRows(0, true);

        if (this.deferEmptyText !== true) {
            this.applyEmptyText();
        }
        
        this.grid.fireEvent('viewready', this.grid);
    },
So, if total column width overflows, the width style on the body takes effect.

But when individual rows are removed using

Code:
    // private
    removeRow : function(row) {
        Ext.removeNode(this.getRow(row));
        this.syncFocusEl(row);
    },
The final row removal does not apply that, so even though the body has the correct width style, because it has no height, it does not cause an overflow, so you get no scrollbars.

Run up the array-grid example, expand column widths so that there is a horizontal scrollbar and then do this:

Code:
g = Ext.getCmp("ext-comp-1002");
s = g.store;
while (s.getCount()) s.removeAt(0);
It ends up with no scrollbar.

Wheras if you did this:

Code:
g = Ext.getCmp("ext-comp-1002");
s = g.store;
s.removeAll();
The scrollbar is displayed.