diff --git a/packages/x-data-grid/src/hooks/features/sorting/useGridSorting.ts b/packages/x-data-grid/src/hooks/features/sorting/useGridSorting.ts
index bd173a9ac7718..427306cff45fa 100644
--- a/packages/x-data-grid/src/hooks/features/sorting/useGridSorting.ts
+++ b/packages/x-data-grid/src/hooks/features/sorting/useGridSorting.ts
@@ -80,7 +80,7 @@ export const useGridSorting = (
const existingIdx = sortModel.findIndex((c) => c.field === field);
let newSortModel = [...sortModel];
if (existingIdx > -1) {
- if (!sortItem) {
+ if (sortItem?.sort == null) {
newSortModel.splice(existingIdx, 1);
} else {
newSortModel.splice(existingIdx, 1, sortItem);
@@ -191,7 +191,7 @@ export const useGridSorting = (
const sortItem = createSortItem(column, direction);
let sortModel: GridSortItem[];
if (!allowMultipleSorting || props.disableMultipleColumnsSorting) {
- sortModel = !sortItem ? [] : [sortItem];
+ sortModel = sortItem?.sort == null ? [] : [sortItem];
} else {
sortModel = upsertSortModel(column.field, sortItem);
}
diff --git a/packages/x-data-grid/src/tests/sorting.DataGrid.test.tsx b/packages/x-data-grid/src/tests/sorting.DataGrid.test.tsx
index f093b81191dba..2ee187cf650b3 100644
--- a/packages/x-data-grid/src/tests/sorting.DataGrid.test.tsx
+++ b/packages/x-data-grid/src/tests/sorting.DataGrid.test.tsx
@@ -150,6 +150,46 @@ describe(' - Sorting', () => {
expect(getColumnValues(0)).to.deep.equal(['10', '0', '5']);
});
+ // See https://github.com/mui/mui-x/issues/12271
+ it('should not keep the sort item with `item.sort = null`', () => {
+ let apiRef: React.MutableRefObject;
+ const onSortModelChange = spy();
+ function TestCase() {
+ apiRef = useGridApiRef();
+ const cols = [{ field: 'id' }];
+ const rows = [{ id: 10 }, { id: 0 }, { id: 5 }];
+
+ return (
+
+
+
+ );
+ }
+
+ render();
+ expect(getColumnValues(0)).to.deep.equal(['10', '0', '5']);
+ const header = getColumnHeaderCell(0);
+
+ // Trigger a `asc` sort
+ fireEvent.click(header);
+ expect(getColumnValues(0)).to.deep.equal(['0', '5', '10']);
+ expect(onSortModelChange.callCount).to.equal(1);
+ expect(onSortModelChange.lastCall.firstArg).to.deep.equal([{ field: 'id', sort: 'asc' }]);
+
+ // Clear the sort using `apiRef`
+ act(() => apiRef.current.sortColumn('id', null));
+ expect(getColumnValues(0)).to.deep.equal(['10', '0', '5']);
+ expect(onSortModelChange.callCount).to.equal(2);
+
+ // Confirm that the sort item is cleared and not passed to `onSortModelChange`
+ expect(onSortModelChange.lastCall.firstArg).to.deep.equal([]);
+ });
+
it('should always set correct `aria-sort` attribute', () => {
const cols = [{ field: 'id' }];
const rows = [{ id: 10 }, { id: 0 }, { id: 5 }];