Skip to content

Commit 98dd066

Browse files
authored
Merge branch 'master' into experimental-toolbar
2 parents b518508 + 54cc876 commit 98dd066

File tree

65 files changed

+2298
-65
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2298
-65
lines changed

docs/data/pages.ts

+5
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,11 @@ const pages: MuiPage[] = [
569569
{ pathname: '/x/react-tree-view/rich-tree-view/customization' },
570570
{ pathname: '/x/react-tree-view/rich-tree-view/focus' },
571571
{ pathname: '/x/react-tree-view/rich-tree-view/editing', newFeature: true },
572+
{
573+
pathname: '/x/react-tree-view/rich-tree-view/lazy-loading',
574+
plan: 'pro',
575+
newFeature: true,
576+
},
572577
{ pathname: '/x/react-tree-view/rich-tree-view/ordering', plan: 'pro', newFeature: true },
573578
],
574579
},

docs/data/tree-view/rich-tree-view/editing/editing.md

+25
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,28 @@ apiRef.current.updateItemLabel(
9797
```
9898

9999
{{"demo": "ApiMethodUpdateItemLabel.js"}}
100+
101+
## Editing lazy loaded children
102+
103+
To store the updated item labels on your server use the `onItemLabelChange` callback function.
104+
105+
Changes to the label are not automatically updated in the `dataSourceCache` and will need to be updated manually.
106+
107+
```tsx
108+
const handleItemLabelChange = (itemId: TreeViewItemId, newLabel: string) => {
109+
// update your cache here
110+
};
111+
112+
<RichTreeViewPro
113+
items={[]}
114+
onItemLabelChange={handleItemLabelChange}
115+
isItemEditable
116+
dataSource={{
117+
getChildrenCount: (item) => item?.childrenCount as number,
118+
getTreeItems: fetchData,
119+
}}
120+
{...otherProps}
121+
/>;
122+
```
123+
124+
Visit the dedicated page for [lazy loading](/x/react-tree-view/rich-tree-view/lazy-loading/#lazy-loading-and-label-editing) to read more.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
import Box from '@mui/material/Box';
3+
import Typography from '@mui/material/Typography';
4+
import Slider from '@mui/material/Slider';
5+
import {
6+
randomInt,
7+
randomName,
8+
randomId,
9+
randomBoolean,
10+
} from '@mui/x-data-grid-generator';
11+
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
12+
13+
function getSliderAriaValueText(value) {
14+
return `${value}°C`;
15+
}
16+
17+
export default function BasicLazyLoading() {
18+
const [latency, setLatency] = React.useState(1000);
19+
20+
const handleSliderChange = (_event, newLatency) => {
21+
setLatency(newLatency);
22+
};
23+
24+
const fetchData = async () => {
25+
const length = randomInt(5, 10);
26+
const rows = Array.from({ length }, () => ({
27+
id: randomId(),
28+
label: randomName({}, {}),
29+
...(randomBoolean() ? { childrenCount: length } : {}),
30+
}));
31+
32+
return new Promise((resolve) => {
33+
setTimeout(() => {
34+
resolve(rows);
35+
}, latency);
36+
});
37+
};
38+
39+
return (
40+
<Box sx={{ width: '300px' }}>
41+
<Box sx={{ width: 250 }}>
42+
<Typography id="latency-slider" gutterBottom>
43+
Loading latency: {latency} (ms)
44+
</Typography>
45+
<Slider
46+
value={latency}
47+
onChange={handleSliderChange}
48+
aria-labelledby="latency-slider"
49+
min={500}
50+
max={10000}
51+
shiftStep={1000}
52+
step={500}
53+
marks
54+
getAriaValueText={getSliderAriaValueText}
55+
valueLabelDisplay="auto"
56+
/>
57+
</Box>
58+
<RichTreeViewPro
59+
items={[]}
60+
experimentalFeatures={{ lazyLoading: true }}
61+
dataSource={{
62+
getChildrenCount: (item) => item?.childrenCount,
63+
getTreeItems: fetchData,
64+
}}
65+
/>
66+
</Box>
67+
);
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import * as React from 'react';
2+
import Box from '@mui/material/Box';
3+
import Typography from '@mui/material/Typography';
4+
import Slider from '@mui/material/Slider';
5+
import {
6+
randomInt,
7+
randomName,
8+
randomId,
9+
randomBoolean,
10+
} from '@mui/x-data-grid-generator';
11+
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
12+
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
13+
14+
type ItemType = TreeViewBaseItem<{
15+
id: string;
16+
label: string;
17+
childrenCount?: number;
18+
}>;
19+
20+
function getSliderAriaValueText(value: number) {
21+
return `${value}°C`;
22+
}
23+
24+
export default function BasicLazyLoading() {
25+
const [latency, setLatency] = React.useState(1000);
26+
27+
const handleSliderChange = (_event: Event, newLatency: number | number[]) => {
28+
setLatency(newLatency as number);
29+
};
30+
31+
const fetchData = async (): Promise<ItemType[]> => {
32+
const length: number = randomInt(5, 10);
33+
const rows = Array.from({ length }, () => ({
34+
id: randomId(),
35+
label: randomName({}, {}),
36+
...(randomBoolean() ? { childrenCount: length } : {}),
37+
}));
38+
39+
return new Promise((resolve) => {
40+
setTimeout(() => {
41+
resolve(rows);
42+
}, latency);
43+
});
44+
};
45+
46+
return (
47+
<Box sx={{ width: '300px' }}>
48+
<Box sx={{ width: 250 }}>
49+
<Typography id="latency-slider" gutterBottom>
50+
Loading latency: {latency} (ms)
51+
</Typography>
52+
<Slider
53+
value={latency}
54+
onChange={handleSliderChange}
55+
aria-labelledby="latency-slider"
56+
min={500}
57+
max={10000}
58+
shiftStep={1000}
59+
step={500}
60+
marks
61+
getAriaValueText={getSliderAriaValueText}
62+
valueLabelDisplay="auto"
63+
/>
64+
</Box>
65+
<RichTreeViewPro
66+
items={[]}
67+
experimentalFeatures={{ lazyLoading: true }}
68+
dataSource={{
69+
getChildrenCount: (item) => item?.childrenCount as number,
70+
getTreeItems: fetchData,
71+
}}
72+
/>
73+
</Box>
74+
);
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from 'react';
2+
import Button from '@mui/material/Button';
3+
import Stack from '@mui/material/Stack';
4+
import { randomName, randomId } from '@mui/x-data-grid-generator';
5+
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
6+
import { initialItems } from './items';
7+
8+
export default function ErrorManagement() {
9+
const [failRequests, setFailRequests] = React.useState(false);
10+
const fetchData = async () => {
11+
const rows = Array.from({ length: 10 }, () => ({
12+
id: randomId(),
13+
label: randomName({}, {}),
14+
childrenCount: 10,
15+
}));
16+
17+
// make the promise fail conditionally
18+
return new Promise((resolve, reject) => {
19+
setTimeout(() => {
20+
if (failRequests) {
21+
reject(new Error('Error fetching data'));
22+
} else {
23+
resolve(rows);
24+
}
25+
}, 1000);
26+
});
27+
};
28+
29+
return (
30+
<Stack spacing={2} sx={{ width: '300px' }}>
31+
<Button
32+
onClick={() => setFailRequests((prev) => !prev)}
33+
variant="outlined"
34+
fullWidth
35+
>
36+
{failRequests ? 'Resolve requests' : 'Fail Requests'}
37+
</Button>
38+
<RichTreeViewPro
39+
items={initialItems}
40+
experimentalFeatures={{ lazyLoading: true }}
41+
dataSource={{
42+
getChildrenCount: (item) => item?.childrenCount,
43+
getTreeItems: fetchData,
44+
}}
45+
/>
46+
</Stack>
47+
);
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import * as React from 'react';
2+
import Button from '@mui/material/Button';
3+
import Stack from '@mui/material/Stack';
4+
import { randomName, randomId } from '@mui/x-data-grid-generator';
5+
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
6+
import { initialItems, ItemType } from './items';
7+
8+
export default function ErrorManagement() {
9+
const [failRequests, setFailRequests] = React.useState(false);
10+
const fetchData = async (): Promise<ItemType[]> => {
11+
const rows = Array.from({ length: 10 }, () => ({
12+
id: randomId(),
13+
label: randomName({}, {}),
14+
childrenCount: 10,
15+
}));
16+
17+
// make the promise fail conditionally
18+
return new Promise((resolve, reject) => {
19+
setTimeout(() => {
20+
if (failRequests) {
21+
reject(new Error('Error fetching data'));
22+
} else {
23+
resolve(rows);
24+
}
25+
}, 1000);
26+
});
27+
};
28+
29+
return (
30+
<Stack spacing={2} sx={{ width: '300px' }}>
31+
<Button
32+
onClick={() => setFailRequests((prev) => !prev)}
33+
variant="outlined"
34+
fullWidth
35+
>
36+
{failRequests ? 'Resolve requests' : 'Fail Requests'}
37+
</Button>
38+
<RichTreeViewPro
39+
items={initialItems}
40+
experimentalFeatures={{ lazyLoading: true }}
41+
dataSource={{
42+
getChildrenCount: (item) => item?.childrenCount as number,
43+
getTreeItems: fetchData,
44+
}}
45+
/>
46+
</Stack>
47+
);
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Button
2+
onClick={() => setFailRequests((prev) => !prev)}
3+
variant="outlined"
4+
fullWidth
5+
>
6+
{failRequests ? 'Resolve requests' : 'Fail Requests'}
7+
</Button>
8+
<RichTreeViewPro
9+
items={initialItems}
10+
experimentalFeatures={{ lazyLoading: true }}
11+
dataSource={{
12+
getChildrenCount: (item) => item?.childrenCount as number,
13+
getTreeItems: fetchData,
14+
}}
15+
/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import * as React from 'react';
2+
import { RichTreeViewPro } from '@mui/x-tree-view-pro/RichTreeViewPro';
3+
import {
4+
randomInt,
5+
randomName,
6+
randomId,
7+
randomBoolean,
8+
} from '@mui/x-data-grid-generator';
9+
10+
import {
11+
QueryClient,
12+
QueryClientProvider,
13+
useQueryClient,
14+
} from '@tanstack/react-query';
15+
16+
const queryClient = new QueryClient();
17+
18+
const items = [];
19+
20+
const fetchData = async (_parentId) => {
21+
const length = randomInt(5, 10);
22+
const rows = Array.from({ length }, () => ({
23+
id: randomId(),
24+
label: randomName({}, {}),
25+
...(randomBoolean() ? { childrenCount: length } : {}),
26+
}));
27+
28+
return new Promise((resolve) => {
29+
setTimeout(() => {
30+
resolve(rows);
31+
}, 1000);
32+
});
33+
};
34+
35+
export function FetchChildren() {
36+
const myQueryClient = useQueryClient();
37+
38+
const fetchTreeItems = async (parentId) => {
39+
const queryKey = parentId ? ['treeItems', parentId] : ['treeItems', 'root'];
40+
const data = await myQueryClient.fetchQuery({
41+
queryKey,
42+
queryFn: () => fetchData(parentId),
43+
});
44+
return data;
45+
};
46+
47+
return (
48+
<RichTreeViewPro
49+
items={items}
50+
experimentalFeatures={{ lazyLoading: true }}
51+
dataSource={{
52+
getChildrenCount: (item) => item?.childrenCount,
53+
getTreeItems: fetchTreeItems,
54+
}}
55+
/>
56+
);
57+
}
58+
59+
export default function FetchingWithReactQuery() {
60+
return (
61+
<QueryClientProvider client={queryClient}>
62+
<FetchChildren />
63+
</QueryClientProvider>
64+
);
65+
}

0 commit comments

Comments
 (0)