@mui/x-data-grid-pro
Version:
The Pro plan edition of the MUI X Data Grid components.
246 lines (245 loc) • 10.2 kB
JavaScript
"use strict";
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridDataSourceBasePro = exports.INITIAL_STATE = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
var _xDataGrid = require("@mui/x-data-grid");
var _internals = require("@mui/x-data-grid/internals");
var _warning = require("@mui/x-internals/warning");
var _utils = require("./utils");
var _gridDataSourceSelector = require("./gridDataSourceSelector");
const INITIAL_STATE = exports.INITIAL_STATE = {
loading: {},
errors: {}
};
const useGridDataSourceBasePro = (apiRef, props, options = {}) => {
const groupsToAutoFetch = (0, _xDataGrid.useGridSelector)(apiRef, _internals.gridRowGroupsToFetchSelector);
const nestedDataManager = (0, _useLazyRef.default)(() => new _utils.NestedDataManager(apiRef)).current;
const scheduledGroups = React.useRef(0);
const clearDataSourceState = React.useCallback(() => {
nestedDataManager.clear();
scheduledGroups.current = 0;
const dataSourceState = apiRef.current.state.dataSource;
if (dataSourceState !== INITIAL_STATE) {
apiRef.current.resetDataSourceState();
}
return null;
}, [apiRef, nestedDataManager]);
const handleEditRow = React.useCallback((params, updatedRow) => {
const groupKeys = (0, _utils.getGroupKeys)((0, _xDataGrid.gridRowTreeSelector)(apiRef), params.rowId);
apiRef.current.updateNestedRows([updatedRow], groupKeys);
if (updatedRow && !(0, _isDeepEqual.isDeepEqual)(updatedRow, params.previousRow)) {
// Reset the outdated cache, only if the row is _actually_ updated
apiRef.current.dataSource.cache.clear();
}
}, [apiRef]);
const {
api,
debouncedFetchRows,
strategyProcessor,
events,
cacheChunkManager,
cache
} = (0, _internals.useGridDataSourceBase)(apiRef, props, (0, _extends2.default)({
fetchRowChildren: nestedDataManager.queue,
clearDataSourceState,
handleEditRow
}, options));
const setStrategyAvailability = React.useCallback(() => {
apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, _internals.DataSourceRowsUpdateStrategy.Default, props.dataSource && !props.lazyLoading ? () => true : () => false);
}, [apiRef, props.dataSource, props.lazyLoading]);
const onDataSourceErrorProp = props.onDataSourceError;
const fetchRowChildren = React.useCallback(async id => {
const pipedParams = apiRef.current.unstable_applyPipeProcessors('getRowsParams', {});
if (!props.treeData && (pipedParams.groupFields?.length ?? 0) === 0) {
nestedDataManager.clearPendingRequest(id);
return;
}
const getRows = props.dataSource?.getRows;
if (!getRows) {
nestedDataManager.clearPendingRequest(id);
return;
}
const rowNode = apiRef.current.getRowNode(id);
if (!rowNode) {
nestedDataManager.clearPendingRequest(id);
return;
}
const fetchParams = (0, _extends2.default)({}, (0, _internals.gridGetRowsParamsSelector)(apiRef), pipedParams, {
groupKeys: rowNode.path
});
const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
const cachedData = responses.some(response => response === undefined) ? undefined : _internals.CacheChunkManager.mergeResponses(responses);
if (cachedData !== undefined) {
const rows = cachedData.rows;
nestedDataManager.setRequestSettled(id);
apiRef.current.updateNestedRows(rows, rowNode.path);
if (cachedData.rowCount !== undefined) {
apiRef.current.setRowCount(cachedData.rowCount);
}
apiRef.current.setRowChildrenExpansion(id, true);
apiRef.current.dataSource.setChildrenLoading(id, false);
return;
}
const existingError = (0, _gridDataSourceSelector.gridDataSourceErrorsSelector)(apiRef)[id] ?? null;
if (existingError) {
apiRef.current.dataSource.setChildrenFetchError(id, null);
}
try {
const getRowsResponse = await getRows(fetchParams);
if (!apiRef.current.getRowNode(id)) {
// The row has been removed from the grid
nestedDataManager.clearPendingRequest(id);
return;
}
if (nestedDataManager.getRequestStatus(id) === _utils.RequestStatus.UNKNOWN) {
apiRef.current.dataSource.setChildrenLoading(id, false);
return;
}
nestedDataManager.setRequestSettled(id);
const cacheResponses = cacheChunkManager.splitResponse(fetchParams, getRowsResponse);
cacheResponses.forEach((response, key) => {
cache.set(key, response);
});
if (getRowsResponse.rowCount !== undefined) {
apiRef.current.setRowCount(getRowsResponse.rowCount);
}
// Remove existing outdated rows before setting the new ones
const rowsToDelete = [];
getRowsResponse.rows.forEach(row => {
const rowId = (0, _xDataGrid.gridRowIdSelector)(apiRef, row);
const treeNode = (0, _xDataGrid.gridRowNodeSelector)(apiRef, rowId);
if (treeNode) {
rowsToDelete.push({
id: rowId,
_action: 'delete'
});
}
});
if (rowsToDelete.length > 0) {
// TODO: Make this happen in a single pass by modifying the pre-processing of the rows
apiRef.current.updateNestedRows(rowsToDelete, rowNode.path);
}
apiRef.current.updateNestedRows(getRowsResponse.rows, rowNode.path);
apiRef.current.setRowChildrenExpansion(id, true);
} catch (error) {
const childrenFetchError = error;
apiRef.current.dataSource.setChildrenFetchError(id, childrenFetchError);
if (typeof onDataSourceErrorProp === 'function') {
onDataSourceErrorProp(new _xDataGrid.GridGetRowsError({
message: childrenFetchError.message,
params: fetchParams,
cause: childrenFetchError
}));
} else if (process.env.NODE_ENV !== 'production') {
(0, _warning.warnOnce)(['MUI X: A call to `dataSource.getRows()` threw an error which was not handled because `onDataSourceError()` is missing.', 'To handle the error pass a callback to the `onDataSourceError` prop, for example `<DataGrid onDataSourceError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/server-side-data/#error-handling.'], 'error');
}
} finally {
apiRef.current.dataSource.setChildrenLoading(id, false);
nestedDataManager.setRequestSettled(id);
}
}, [nestedDataManager, cacheChunkManager, cache, onDataSourceErrorProp, apiRef, props.treeData, props.dataSource?.getRows]);
const setChildrenLoading = React.useCallback((parentId, isLoading) => {
apiRef.current.setState(state => {
if (!state.dataSource.loading[parentId] && isLoading === false) {
return state;
}
const newLoadingState = (0, _extends2.default)({}, state.dataSource.loading);
if (isLoading === false) {
delete newLoadingState[parentId];
} else {
newLoadingState[parentId] = isLoading;
}
return (0, _extends2.default)({}, state, {
dataSource: (0, _extends2.default)({}, state.dataSource, {
loading: newLoadingState
})
});
});
}, [apiRef]);
const setChildrenFetchError = React.useCallback((parentId, error) => {
apiRef.current.setState(state => {
const newErrorsState = (0, _extends2.default)({}, state.dataSource.errors);
if (error === null && newErrorsState[parentId] !== undefined) {
delete newErrorsState[parentId];
} else {
newErrorsState[parentId] = error;
}
return (0, _extends2.default)({}, state, {
dataSource: (0, _extends2.default)({}, state.dataSource, {
errors: newErrorsState
})
});
});
}, [apiRef]);
const resetDataSourceState = React.useCallback(() => {
apiRef.current.setState(state => {
return (0, _extends2.default)({}, state, {
dataSource: INITIAL_STATE
});
});
}, [apiRef]);
const removeChildrenRows = React.useCallback(parentId => {
const rowNode = (0, _xDataGrid.gridRowNodeSelector)(apiRef, parentId);
if (!rowNode || rowNode.type !== 'group' || rowNode.children.length === 0) {
return;
}
const removedRows = [];
const traverse = nodeId => {
const node = (0, _xDataGrid.gridRowNodeSelector)(apiRef, nodeId);
if (!node) {
return;
}
if (node.type === 'group' && node.children.length > 0) {
node.children.forEach(traverse);
}
removedRows.push({
id: nodeId,
_action: 'delete'
});
};
rowNode.children.forEach(traverse);
if (removedRows.length > 0) {
apiRef.current.updateNestedRows(removedRows, rowNode.path);
}
}, [apiRef]);
const dataSourceApi = {
dataSource: (0, _extends2.default)({}, api.public.dataSource, {
setChildrenLoading,
setChildrenFetchError
})
};
const dataSourcePrivateApi = {
fetchRowChildren,
resetDataSourceState,
removeChildrenRows
};
React.useEffect(() => {
if (groupsToAutoFetch && groupsToAutoFetch.length && scheduledGroups.current < groupsToAutoFetch.length) {
const groupsToSchedule = groupsToAutoFetch.slice(scheduledGroups.current);
nestedDataManager.queue(groupsToSchedule);
scheduledGroups.current = groupsToAutoFetch.length;
}
}, [apiRef, nestedDataManager, groupsToAutoFetch]);
return {
api: {
public: dataSourceApi,
private: dataSourcePrivateApi
},
debouncedFetchRows,
strategyProcessor,
events,
setStrategyAvailability,
cacheChunkManager,
cache
};
};
exports.useGridDataSourceBasePro = useGridDataSourceBasePro;