@mui/x-data-grid
Version:
The Community plan edition of the MUI X Data Grid components.
221 lines (219 loc) • 10.1 kB
JavaScript
'use client';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useGridDataSourceBase = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var React = _interopRequireWildcard(require("react"));
var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
var _debounce = _interopRequireDefault(require("@mui/utils/debounce"));
var _warning = require("@mui/x-internals/warning");
var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
var _gridRowsUtils = require("../rows/gridRowsUtils");
var _utils = require("../../../utils/utils");
var _strategyProcessing = require("../../core/strategyProcessing");
var _useGridSelector = require("../../utils/useGridSelector");
var _gridPaginationSelector = require("../pagination/gridPaginationSelector");
var _gridDataSourceSelector = require("./gridDataSourceSelector");
var _utils2 = require("./utils");
var _cache = require("./cache");
var _gridDataSourceError = require("./gridDataSourceError");
const _excluded = ["skipCache"];
const noopCache = {
clear: () => {},
get: () => undefined,
set: () => {}
};
function getCache(cacheProp, options = {}) {
if (cacheProp === null) {
return noopCache;
}
return cacheProp ?? new _cache.GridDataSourceCacheDefault(options);
}
const useGridDataSourceBase = (apiRef, props, options = {}) => {
const setStrategyAvailability = React.useCallback(() => {
apiRef.current.setStrategyAvailability(_strategyProcessing.GridStrategyGroup.DataSource, _utils2.DataSourceRowsUpdateStrategy.Default, props.dataSource ? () => true : () => false);
}, [apiRef, props.dataSource]);
const [defaultRowsUpdateStrategyActive, setDefaultRowsUpdateStrategyActive] = React.useState(false);
const paginationModel = (0, _useGridSelector.useGridSelector)(apiRef, _gridPaginationSelector.gridPaginationModelSelector);
const lastRequestId = React.useRef(0);
const onDataSourceErrorProp = props.onDataSourceError;
const cacheChunkManager = (0, _useLazyRef.default)(() => {
if (!props.pagination) {
return new _utils2.CacheChunkManager(paginationModel.pageSize);
}
const sortedPageSizeOptions = props.pageSizeOptions.map(option => typeof option === 'number' ? option : option.value).sort((a, b) => a - b);
const cacheChunkSize = Math.min(paginationModel.pageSize, sortedPageSizeOptions[0]);
return new _utils2.CacheChunkManager(cacheChunkSize);
}).current;
const [cache, setCache] = React.useState(() => getCache(props.dataSourceCache, options.cacheOptions));
const fetchRows = React.useCallback(async (parentId, params) => {
const getRows = props.dataSource?.getRows;
if (!getRows) {
return;
}
if (parentId && parentId !== _gridRowsUtils.GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
options.fetchRowChildren?.([parentId]);
return;
}
options.clearDataSourceState?.();
const _ref = params || {},
{
skipCache
} = _ref,
getRowsParams = (0, _objectWithoutPropertiesLoose2.default)(_ref, _excluded);
const fetchParams = (0, _extends2.default)({}, (0, _gridDataSourceSelector.gridGetRowsParamsSelector)(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}), getRowsParams);
const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
if (!skipCache && responses.every(response => response !== undefined)) {
apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
response: _utils2.CacheChunkManager.mergeResponses(responses),
fetchParams
});
return;
}
// Manage loading state only for the default strategy
if (defaultRowsUpdateStrategyActive || apiRef.current.getRowsCount() === 0) {
apiRef.current.setLoading(true);
}
const requestId = lastRequestId.current + 1;
lastRequestId.current = requestId;
try {
const getRowsResponse = await getRows(fetchParams);
const cacheResponses = cacheChunkManager.splitResponse(fetchParams, getRowsResponse);
cacheResponses.forEach((response, key) => cache.set(key, response));
if (lastRequestId.current === requestId) {
apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
response: getRowsResponse,
fetchParams
});
}
} catch (originalError) {
if (lastRequestId.current === requestId) {
apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
error: originalError,
fetchParams
});
if (typeof onDataSourceErrorProp === 'function') {
onDataSourceErrorProp(new _gridDataSourceError.GridGetRowsError({
message: originalError?.message,
params: fetchParams,
cause: originalError
}));
} 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 {
if (defaultRowsUpdateStrategyActive && lastRequestId.current === requestId) {
apiRef.current.setLoading(false);
}
}
}, [cacheChunkManager, cache, apiRef, defaultRowsUpdateStrategyActive, props.dataSource?.getRows, onDataSourceErrorProp, options, props.signature]);
const handleStrategyActivityChange = React.useCallback(() => {
setDefaultRowsUpdateStrategyActive(apiRef.current.getActiveStrategy(_strategyProcessing.GridStrategyGroup.DataSource) === _utils2.DataSourceRowsUpdateStrategy.Default);
}, [apiRef]);
const handleDataUpdate = React.useCallback(params => {
if ('error' in params) {
apiRef.current.setRows([]);
return;
}
const {
response
} = params;
if (response.rowCount !== undefined) {
apiRef.current.setRowCount(response.rowCount);
}
apiRef.current.setRows(response.rows);
apiRef.current.unstable_applyPipeProcessors('processDataSourceRows', {
params: params.fetchParams,
response
}, true);
}, [apiRef]);
const dataSourceUpdateRow = props.dataSource?.updateRow;
const handleEditRowOption = options.handleEditRow;
const editRow = React.useCallback(async params => {
if (!dataSourceUpdateRow) {
return undefined;
}
try {
const finalRowUpdate = await dataSourceUpdateRow(params);
if (typeof handleEditRowOption === 'function') {
handleEditRowOption(params, finalRowUpdate);
return finalRowUpdate;
}
apiRef.current.updateNestedRows([finalRowUpdate], []);
if (finalRowUpdate && !(0, _isDeepEqual.isDeepEqual)(finalRowUpdate, params.previousRow)) {
// Reset the outdated cache, only if the row is _actually_ updated
apiRef.current.dataSource.cache.clear();
}
return finalRowUpdate;
} catch (errorThrown) {
if (typeof onDataSourceErrorProp === 'function') {
onDataSourceErrorProp(new _gridDataSourceError.GridUpdateRowError({
message: errorThrown?.message,
params,
cause: errorThrown
}));
} else if (process.env.NODE_ENV !== 'production') {
(0, _warning.warnOnce)(['MUI X: A call to `dataSource.updateRow()` 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');
}
throw errorThrown; // Let the caller handle the error further
}
}, [apiRef, dataSourceUpdateRow, onDataSourceErrorProp, handleEditRowOption]);
const dataSourceApi = {
dataSource: {
fetchRows,
cache,
editRow
}
};
const debouncedFetchRows = React.useMemo(() => (0, _debounce.default)(fetchRows, 0), [fetchRows]);
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
if (props.dataSourceCache === undefined) {
return;
}
const newCache = getCache(props.dataSourceCache, options.cacheOptions);
setCache(prevCache => prevCache !== newCache ? newCache : prevCache);
}, [props.dataSourceCache, options.cacheOptions]);
React.useEffect(() => {
if (props.dataSource) {
apiRef.current.dataSource.cache.clear();
apiRef.current.dataSource.fetchRows();
}
return () => {
// ignore the current request on unmount
lastRequestId.current += 1;
};
}, [apiRef, props.dataSource]);
return {
api: {
public: dataSourceApi
},
debouncedFetchRows,
strategyProcessor: {
strategyName: _utils2.DataSourceRowsUpdateStrategy.Default,
group: 'dataSourceRowsUpdate',
processor: handleDataUpdate
},
setStrategyAvailability,
cacheChunkManager,
cache,
events: {
strategyAvailabilityChange: handleStrategyActivityChange,
sortModelChange: (0, _utils.runIf)(defaultRowsUpdateStrategyActive, () => debouncedFetchRows()),
filterModelChange: (0, _utils.runIf)(defaultRowsUpdateStrategyActive, () => debouncedFetchRows()),
paginationModelChange: (0, _utils.runIf)(defaultRowsUpdateStrategyActive, () => debouncedFetchRows())
}
};
};
exports.useGridDataSourceBase = useGridDataSourceBase;
;