@mui/x-data-grid 8.29.0 → 8.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/hooks/utils/useGridSelector.js +25 -22
- package/hooks/utils/useGridSelector.mjs +24 -22
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,8 +5,26 @@
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## 8.29.1
|
|
9
|
+
|
|
10
|
+
_Jun 11, 2026_
|
|
11
|
+
|
|
12
|
+
### Data Grid
|
|
13
|
+
|
|
14
|
+
#### `@mui/x-data-grid@8.29.1`
|
|
15
|
+
|
|
16
|
+
- [DataGrid] Prevent React state update before mount (#22749) @arminmeh
|
|
17
|
+
|
|
18
|
+
#### `@mui/x-data-grid-pro@8.29.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
19
|
+
|
|
20
|
+
Same changes as in `@mui/x-data-grid@8.29.1`.
|
|
21
|
+
|
|
22
|
+
#### `@mui/x-data-grid-premium@8.29.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
23
|
+
|
|
24
|
+
Same changes as in `@mui/x-data-grid-pro@8.29.1`.
|
|
25
|
+
|
|
8
26
|
## 8.29.0
|
|
9
|
-
|
|
27
|
+
|
|
10
28
|
_Jun 5, 2026_
|
|
11
29
|
|
|
12
30
|
We'd like to extend a big thank you to the 2 contributors who made this release possible. Here are some highlights ✨:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
5
|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
5
6
|
Object.defineProperty(exports, "__esModule", {
|
|
6
7
|
value: true
|
|
@@ -8,9 +9,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
8
9
|
exports.objectShallowCompare = exports.argsEqual = void 0;
|
|
9
10
|
exports.useGridSelector = useGridSelector;
|
|
10
11
|
var React = _interopRequireWildcard(require("react"));
|
|
12
|
+
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
|
|
11
13
|
var _fastObjectShallowCompare = require("@mui/x-internals/fastObjectShallowCompare");
|
|
12
14
|
var _warning = require("@mui/x-internals/warning");
|
|
13
|
-
var _shim = require("use-sync-external-store/shim");
|
|
14
15
|
var _useLazyRef = require("./useLazyRef");
|
|
15
16
|
const defaultCompare = Object.is;
|
|
16
17
|
const objectShallowCompare = exports.objectShallowCompare = _fastObjectShallowCompare.fastObjectShallowCompare;
|
|
@@ -34,10 +35,10 @@ const createRefs = () => ({
|
|
|
34
35
|
state: null,
|
|
35
36
|
equals: null,
|
|
36
37
|
selector: null,
|
|
37
|
-
args: undefined
|
|
38
|
+
args: undefined,
|
|
39
|
+
storeState: null
|
|
38
40
|
});
|
|
39
41
|
const EMPTY = [];
|
|
40
|
-
const emptyGetSnapshot = () => null;
|
|
41
42
|
function useGridSelector(apiRef, selector, args = undefined, equals = defaultCompare) {
|
|
42
43
|
if (!apiRef.current.state) {
|
|
43
44
|
(0, _warning.warnOnce)(['MUI X: `useGridSelector` has been called before the initialization of the state.', 'This hook can only be used inside the context of the grid.']);
|
|
@@ -48,6 +49,9 @@ function useGridSelector(apiRef, selector, args = undefined, equals = defaultCom
|
|
|
48
49
|
// We don't use an initialization function to avoid allocations
|
|
49
50
|
didInit ? null : selector(apiRef, args));
|
|
50
51
|
refs.current.state = state;
|
|
52
|
+
if (!didInit) {
|
|
53
|
+
refs.current.storeState = apiRef.current.store.state;
|
|
54
|
+
}
|
|
51
55
|
refs.current.equals = equals;
|
|
52
56
|
refs.current.selector = selector;
|
|
53
57
|
const prevArgs = refs.current.args;
|
|
@@ -58,35 +62,34 @@ function useGridSelector(apiRef, selector, args = undefined, equals = defaultCom
|
|
|
58
62
|
refs.current.state = newState;
|
|
59
63
|
setState(newState);
|
|
60
64
|
}
|
|
65
|
+
refs.current.storeState = apiRef.current.store.state;
|
|
61
66
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
refs.current.subscription = apiRef.current.store.subscribe(() => {
|
|
67
|
+
const updateState = React.useCallback(() => {
|
|
68
|
+
const storeState = apiRef.current.store.state;
|
|
69
|
+
if (refs.current.storeState !== storeState) {
|
|
67
70
|
const newState = refs.current.selector(apiRef, refs.current.args);
|
|
71
|
+
refs.current.storeState = storeState;
|
|
68
72
|
if (!refs.current.equals(refs.current.state, newState)) {
|
|
69
73
|
refs.current.state = newState;
|
|
70
74
|
setState(newState);
|
|
71
75
|
}
|
|
72
|
-
}
|
|
73
|
-
return null;
|
|
76
|
+
}
|
|
74
77
|
},
|
|
75
78
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
76
79
|
EMPTY);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
|
|
81
|
+
// Why subscribe in an effect instead of during render: a component can render without
|
|
82
|
+
// ever mounting (e.g. when it suspends during hydration). If it subscribed during render,
|
|
83
|
+
// it could receive a store update and call `setState` before being mounted (#17077).
|
|
84
|
+
// Effects only run for mounted components, so subscribing here is safe.
|
|
85
|
+
//
|
|
86
|
+
// Using a layout effect because the store may already have changed
|
|
87
|
+
// between render and mount (e.g. from a child's ref callback or layout effect).
|
|
88
|
+
// `updateState()` picks up such changes, so the corrected value is shown right away instead of in a second frame.
|
|
89
|
+
(0, _useEnhancedEffect.default)(() => {
|
|
90
|
+
updateState();
|
|
91
|
+
return apiRef.current.store.subscribe(updateState);
|
|
88
92
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
93
|
}, EMPTY);
|
|
90
|
-
(0, _shim.useSyncExternalStore)(unsubscribe, subscribe, emptyGetSnapshot);
|
|
91
94
|
return state;
|
|
92
95
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
4
5
|
import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare';
|
|
5
6
|
import { warnOnce } from '@mui/x-internals/warning';
|
|
6
|
-
import { useSyncExternalStore } from 'use-sync-external-store/shim';
|
|
7
7
|
import { useLazyRef } from "./useLazyRef.mjs";
|
|
8
8
|
const defaultCompare = Object.is;
|
|
9
9
|
export const objectShallowCompare = fastObjectShallowCompare;
|
|
@@ -26,10 +26,10 @@ const createRefs = () => ({
|
|
|
26
26
|
state: null,
|
|
27
27
|
equals: null,
|
|
28
28
|
selector: null,
|
|
29
|
-
args: undefined
|
|
29
|
+
args: undefined,
|
|
30
|
+
storeState: null
|
|
30
31
|
});
|
|
31
32
|
const EMPTY = [];
|
|
32
|
-
const emptyGetSnapshot = () => null;
|
|
33
33
|
export function useGridSelector(apiRef, selector, args = undefined, equals = defaultCompare) {
|
|
34
34
|
if (!apiRef.current.state) {
|
|
35
35
|
warnOnce(['MUI X: `useGridSelector` has been called before the initialization of the state.', 'This hook can only be used inside the context of the grid.']);
|
|
@@ -40,6 +40,9 @@ export function useGridSelector(apiRef, selector, args = undefined, equals = def
|
|
|
40
40
|
// We don't use an initialization function to avoid allocations
|
|
41
41
|
didInit ? null : selector(apiRef, args));
|
|
42
42
|
refs.current.state = state;
|
|
43
|
+
if (!didInit) {
|
|
44
|
+
refs.current.storeState = apiRef.current.store.state;
|
|
45
|
+
}
|
|
43
46
|
refs.current.equals = equals;
|
|
44
47
|
refs.current.selector = selector;
|
|
45
48
|
const prevArgs = refs.current.args;
|
|
@@ -50,35 +53,34 @@ export function useGridSelector(apiRef, selector, args = undefined, equals = def
|
|
|
50
53
|
refs.current.state = newState;
|
|
51
54
|
setState(newState);
|
|
52
55
|
}
|
|
56
|
+
refs.current.storeState = apiRef.current.store.state;
|
|
53
57
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
refs.current.subscription = apiRef.current.store.subscribe(() => {
|
|
58
|
+
const updateState = React.useCallback(() => {
|
|
59
|
+
const storeState = apiRef.current.store.state;
|
|
60
|
+
if (refs.current.storeState !== storeState) {
|
|
59
61
|
const newState = refs.current.selector(apiRef, refs.current.args);
|
|
62
|
+
refs.current.storeState = storeState;
|
|
60
63
|
if (!refs.current.equals(refs.current.state, newState)) {
|
|
61
64
|
refs.current.state = newState;
|
|
62
65
|
setState(newState);
|
|
63
66
|
}
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
67
|
+
}
|
|
66
68
|
},
|
|
67
69
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
68
70
|
EMPTY);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
|
|
72
|
+
// Why subscribe in an effect instead of during render: a component can render without
|
|
73
|
+
// ever mounting (e.g. when it suspends during hydration). If it subscribed during render,
|
|
74
|
+
// it could receive a store update and call `setState` before being mounted (#17077).
|
|
75
|
+
// Effects only run for mounted components, so subscribing here is safe.
|
|
76
|
+
//
|
|
77
|
+
// Using a layout effect because the store may already have changed
|
|
78
|
+
// between render and mount (e.g. from a child's ref callback or layout effect).
|
|
79
|
+
// `updateState()` picks up such changes, so the corrected value is shown right away instead of in a second frame.
|
|
80
|
+
useEnhancedEffect(() => {
|
|
81
|
+
updateState();
|
|
82
|
+
return apiRef.current.store.subscribe(updateState);
|
|
80
83
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
81
84
|
}, EMPTY);
|
|
82
|
-
useSyncExternalStore(unsubscribe, subscribe, emptyGetSnapshot);
|
|
83
85
|
return state;
|
|
84
86
|
}
|
package/index.js
CHANGED
package/index.mjs
CHANGED